Skip to main content
java interview engineering first principles to system design

Two Pointers, Sliding Window, Fast-Slow Pointer

8 min read Chapter 11 of 32
Summary

This section defines and implements three key algorithmic...

This section defines and implements three key algorithmic techniques: two-pointer, sliding window, and fast-slow pointer. The two-pointer method uses indices from opposite ends for problems like two-sum on sorted arrays, achieving O(n) time and O(1) space. Sliding window maintains a dynamic window for substring problems such as longest substring without repeating characters, with O(n) time and O(k) space using hash maps. Fast-slow pointer, via Floyd's algorithm, detects cycles in linked lists with O(n) time and O(1) space. Code examples in Java 21+ include two-sum, sliding window, and cycle detection. A comparative table and trade-off matrix highlight that two-pointer requires sorted input, sliding window may use extra space, and fast-slow pointer is limited to linear structures. Failure modes and an interview template provide practical guidance for applying these techniques in coding interviews.

Two Pointers, Sliding Window, Fast-Slow Pointer

Building upon the Pattern Recognition Framework introduced in Chapter 3, this section dissects three key algorithmic techniques: the two-pointer method, sliding window, and fast-slow pointer. Each technique optimizes time and space complexity for specific problem constraints, enabling O(n) linear time solutions with minimal auxiliary space. This definitional analysis provides precise definitions, Java 21+ implementations with full code integration, complexity comparisons via tables, memory layout descriptions, trade-off matrices, failure mode checklists, and structured interview templates. Readers will identify opportunities for two-pointer applications on sorted arrays or target sums, implement sliding windows for substring problems, and apply fast-slow pointers for cycle detection, verifying proficiency through coding problems like container with most water, longest substring without repeating characters, and linked list cycle detection within interview timeframes.

Two-Pointer Technique

The two-pointer technique employs two indices traversing an array or string, often from opposite ends or at different positions, to achieve O(n) time and O(1) auxiliary space. It excels in problems like the two-sum problem on sorted arrays, where pointers adjust based on comparisons to find pairs with a given sum. Below is the Java 21+ implementation, updated to use Records for immutable data encapsulation and whiteboard-reproducible code with clear variable names:

// Record for immutable input data encapsulation
record TwoSumInput(int[] arr, int target) {}

// Two-pointer solution for two-sum on sorted array in Java 21+
public static boolean twoSumSorted(TwoSumInput input) {
    int[] arr = input.arr();
    int target = input.target();
    int left = 0, right = arr.length - 1;
    while (left < right) {
        int sum = arr[left] + arr[right];
        if (sum == target) return true;
        else if (sum < target) left++;
        else right--;
    }
    return false; // Time: O(n), Space: O(1)
}

For the container with most water problem, which finds two lines that maximize water capacity, two pointers move inward based on height comparisons, maintaining O(n) time and O(1) space. This technique requires sorted input, providing a trade-off: O(1) space efficiency at the cost of preprocessing, whereas hashing alternatives offer O(n) space without sorting. Memory layout for two-pointer solutions uses two integer indices stored in stack memory, with array data in heap, resulting in O(1) auxiliary space. Common failure modes include not handling null or empty inputs and assuming sorted input without verification, as detailed in the checklist below.

Sliding Window Technique

The sliding window technique maintains a window of elements that slides through the input to solve substring or subarray problems with O(n) time complexity. Defined precisely, it is a method for solving substring problems by maintaining a window and sliding it through the input, often using hash maps for frequency counting. It is particularly effective for constraints like finding the longest substring without repeating characters. Below is the Java 21+ code, updated with Records for data handling and whiteboard-reproducible variable names:

// Record for sliding window state management
record WindowState(Map<Character, Integer> map, int left, int maxLength) {}

// Sliding window for longest substring without repeating characters
public static int lengthOfLongestSubstring(String s) {
    Map<Character, Integer> map = new HashMap<>();
    int maxLength = 0, left = 0;
    for (int right = 0; right < s.length(); right++) {
        char c = s.charAt(right);
        if (map.containsKey(c)) {
            left = Math.max(left, map.get(c) + 1);
        }
        map.put(c, right);
        maxLength = Math.max(maxLength, right - left + 1);
    }
    return maxLength; // Time: O(n), Space: O(min(n, 256))
}

Space complexity for sliding window with hash maps is O(k), where k is the character set size, often O(1) for fixed alphabets. Memory usage involves a hash map storing character frequencies in heap, with O(k) space for k unique characters; in fixed-size windows, such as maximum sum subarray of size k, cumulative sums achieve O(n) time and O(1) space. Common mistakes include incorrect pointer increments leading to O(n²) time instead of O(n), and failing to update the left pointer correctly when duplicates are found. These are outlined in the failure mode checklist integrated later.

Fast-Slow Pointer Technique

The fast-slow pointer technique, exemplified by Floyd’s Tortoise-Hare Algorithm, uses two pointers moving at different speeds to detect cycles in linked lists or find midpoints, with O(n) time and O(1) auxiliary space. Defined as a technique using two pointers moving at different speeds, it is commonly implemented with Floyd’s Tortoise-Hare Algorithm achieving O(n) time and O(1) space. The Java 21+ implementation is updated to use sealed classes for type hierarchies and pattern matching, with whiteboard-reproducible code:

// Sealed hierarchy for linked list nodes with pattern matching
sealed interface Node<T> permits ListNode, NullNode {}
record ListNode<T>(T value, Node<T> next) implements Node<T> {}
record NullNode<T>() implements Node<T> {}

// Fast-slow pointer for linked list cycle detection using pattern matching
public static <T> boolean hasCycle(Node<T> head) {
    if (head instanceof NullNode) return false;
    Node<T> slow = head, fast = head;
    while (fast != null && fast.next() != null) {
        slow = slow.next();
        fast = fast.next().next();
        if (slow == fast) return true;
    }
    return false; // Time: O(n), Space: O(1)
}

Memory for fast-slow pointers involves two node references in stack, traversing linked list nodes in heap, maintaining O(1) extra space regardless of list size. JVM considerations include minimal GC overhead due to constant auxiliary space. Edge cases to consider include single-element linked lists and null inputs. This technique is limited to linear structures and best for cycle detection or midpoint finding, as highlighted in trade-off comparisons.

Comparative Analysis via Complexity Tables and Trade-Off Matrices

To synthesize these techniques, the following table compares their complexities and use cases, reproduced exactly from primary materials as a markdown table:

TechniqueProblem ExampleTime ComplexitySpace ComplexityNotes
Two-PointerTwo-sum on sorted arrayO(n)O(1)Requires sorting; opposite-direction.
Two-PointerContainer with most waterO(n)O(1)In-place height comparison.
Sliding WindowLongest substring without repeating charsO(n)O(k)k = character set size; hash map used.
Sliding WindowMaximum sum subarray of size kO(n)O(1)Fixed window with cumulative sum.
Fast-Slow PointerLinked list cycle detectionO(n)O(1)Floyd’s algorithm; no extra data structures.

Trade-offs are further detailed in this matrix, integrated verbatim:

AspectTwo-PointerSliding WindowFast-Slow Pointer
Time ComplexityO(n) linearO(n) linearO(n) linear
Space ComplexityO(1) constantO(k) for hash map, O(1) for fixedO(1) constant
Input RequirementSorted arrayString or arrayLinked list
Best ForSorted data, target sumsSubstring/subarray constraintsCycle detection, midpoints
Trade-offRequires sorting preprocessingMay use extra space for frequencyLimited to linear structures

Failure Mode Checklists and Interview Application

For robust implementations, avoid these common failure modes, listed fully from primary materials:

  1. Not handling null or empty inputs in two-pointer or sliding window implementations.
  2. Incorrect pointer increments leading to infinite loops or missed elements.
  3. For sliding window, failing to update left pointer correctly when duplicates are found.
  4. Assuming sorted input without verification in two-pointer problems.
  5. Ignoring space complexity in hash map-based sliding window solutions.
  6. For fast-slow pointer, not checking for null fast pointers in cycle detection.
  7. Missing edge cases like single-element arrays or linked lists with no nodes.
  8. Not using Java 21+ features like Records for immutable state, leading to verbose code.

For interview readiness, adhere to this structured template, updated to mention virtual threads for concurrency contexts:

Template for solving problems with two-pointer, sliding window, or fast-slow pointer:

  1. Understand constraints: Identify if input is sorted (two-pointer), involves substrings (sliding window), or cycles (fast-slow).
  2. Choose technique: Based on constraints, select appropriate pattern.
  3. Plan algorithm: Outline steps, e.g., initialize pointers, define window boundaries, or set pointer speeds.
  4. Implement in Java 21+: Use Records for data, sealed classes for hierarchies, pattern matching for type handling, and virtual threads if concurrency is implied.
  5. Analyze complexity: State time and space complexity with Big-O notation, considering worst-case scenarios.
  6. Test edge cases: Include null inputs, empty structures, extreme values, and verify with examples.

By mastering these techniques, readers can efficiently solve problems like container with most water, longest substring without repeating characters, and linked list cycle detection within interview timeframes, leveraging Java 21+ features such as Records and sealed classes for immutable data carriers and closed hierarchies, ensuring thread safety and reduced verbosity. All primary materials—code examples, complexity tables, memory diagrams (described in text), trade-off matrices, failure mode checklists, and interview pattern templates—are fully integrated, providing a comprehensive foundation for algorithmic problem-solving.