Two Pointers and Sliding Window Interview Patterns

Two Pointers and Sliding Window Interview Patterns

Two pointers and sliding window are techniques that turn O(n²) brute-force solutions into O(n). They are among the most frequently tested patterns in coding interviews. This guide covers both techniques with clear templates and the problem types each solves.

Two Pointers: Opposite Direction

Start pointers at both ends of a sorted array and move them toward each other based on the comparison result.

# Two Sum II (sorted array, LeetCode 167):
def two_sum_sorted(nums, target):
    l, r = 0, len(nums) - 1
    while l < r:
        s = nums[l] + nums[r]
        if s == target: return [l+1, r+1]
        elif s < target: l += 1  # need larger sum, move left ptr right
        else: r -= 1              # need smaller sum, move right ptr left
    return []

# Valid Palindrome: same idea — compare from both ends, move inward

Three Sum (LeetCode 15)

def three_sum(nums):
    nums.sort()
    result = []
    for i in range(len(nums) - 2):
        if i > 0 and nums[i] == nums[i-1]: continue  # skip duplicate
        l, r = i + 1, len(nums) - 1
        while l < r:
            s = nums[i] + nums[l] + nums[r]
            if s == 0:
                result.append([nums[i], nums[l], nums[r]])
                while l < r and nums[l] == nums[l+1]: l += 1  # skip duplicates
                while l < r and nums[r] == nums[r-1]: r -= 1
                l += 1; r -= 1
            elif s < 0: l += 1
            else: r -= 1
    return result
# Time O(n log n + n^2) = O(n^2), Space O(1)

Two Pointers: Same Direction (Fast/Slow)

Two pointers move in the same direction at different speeds. Used for linked list cycle detection and in-place array manipulation.

# Remove Duplicates from Sorted Array (LeetCode 26):
def remove_duplicates(nums):
    slow = 0
    for fast in range(1, len(nums)):
        if nums[fast] != nums[slow]:
            slow += 1
            nums[slow] = nums[fast]
    return slow + 1

# Floyd cycle detection (linked list):
def has_cycle(head):
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast: return True
    return False

Sliding Window: Fixed Size

Maintain a window of exactly k elements, slide it one position at a time.

# Maximum Average Subarray of Length K (LeetCode 643):
def find_max_average(nums, k):
    window_sum = sum(nums[:k])
    max_sum = window_sum
    for i in range(k, len(nums)):
        window_sum += nums[i] - nums[i-k]  # add new, remove old
        max_sum = max(max_sum, window_sum)
    return max_sum / k
# Time O(n), Space O(1)

Sliding Window: Variable Size

Expand right pointer to grow the window; shrink left pointer when the constraint is violated.

# Longest Substring Without Repeating Characters (LeetCode 3):
def length_of_longest_substring(s):
    char_set = set()
    l = max_len = 0
    for r in range(len(s)):
        while s[r] in char_set:    # constraint violated: remove from left
            char_set.remove(s[l])
            l += 1
        char_set.add(s[r])
        max_len = max(max_len, r - l + 1)
    return max_len

# Minimum Window Substring (LeetCode 76):
from collections import Counter
def min_window(s, t):
    need = Counter(t)
    missing = len(t)
    l = best_l = best_r = 0
    for r, c in enumerate(s, 1):
        if need[c] > 0: missing -= 1
        need[c] -= 1
        if missing == 0:  # valid window found
            while need[s[l]] < 0:  # shrink from left
                need[s[l]] += 1
                l += 1
            if best_r == 0 or r - l < best_r - best_l:
                best_l, best_r = l, r
            need[s[l]] += 1
            missing += 1
            l += 1
    return s[best_l:best_r]

Common Problem Patterns

Problem Pattern LeetCode
Two sum on sorted array Two pointers, opposite 167, 15, 16, 18
Container with most water Two pointers, opposite 11
In-place array modification Two pointers, same direction 26, 27, 80, 283
Linked list cycle Fast/slow pointers 141, 142, 287
Max/min of fixed window Sliding window, fixed 643, 239
Longest substring with constraint Sliding window, variable 3, 159, 340, 424
Minimum window containing target Sliding window, variable 76, 567, 438

Variable Window Template

def sliding_window(s, k):
    l = 0
    state = {}          # track window state (character counts, etc.)
    result = 0
    for r in range(len(s)):
        # Expand: add s[r] to window state
        state[s[r]] = state.get(s[r], 0) + 1

        # Shrink: while constraint violated, remove s[l]
        while len(state) > k:   # example constraint: at most k distinct chars
            state[s[l]] -= 1
            if state[s[l]] == 0: del state[s[l]]
            l += 1

        # Update result (window is valid here)
        result = max(result, r - l + 1)
    return result

Interview Tips

  • For any “longest/minimum subarray/substring” problem, try sliding window first
  • The variable window shrink loop (while constraint violated) is the key — practice writing it from memory
  • For three sum: sort first, fix one pointer, use two-pointer for the pair — this is the standard O(n²) approach
  • Fast/slow pointer: the distance between them at cycle entry = distance from head to cycle entry (used in LeetCode 142)
  • State your time complexity explicitly: “O(n) because each element enters and leaves the window at most once”

  • Uber Interview Guide
  • Atlassian Interview Guide
  • Snap Interview Guide
  • LinkedIn Interview Guide
  • Apple Interview Guide
  • Meta Interview Guide
  • Scroll to Top