Algorithms
Arrays, Two Pointers & Sliding Window
Arrays are the foundation of nearly every coding interview. Mastering two-pointer techniques and sliding window patterns lets you solve O(nยฒ) brute-force problems in O(n) time. These patterns appear in 30-40% of all FAANG coding questions โ they are non-negotiable.
Core Concepts
- 1Two pointer technique โ convergent: place one pointer at the start, one at the end. Move them toward each other based on a condition. Classic use case: finding a pair that sums to a target in a sorted array. Instead of O(nยฒ) nested loops, you move left pointer right when sum is too small, right pointer left when sum is too large โ O(n) total. The key insight: because the array is sorted, you have perfect information about which direction to move each pointer. Works for: two-sum in sorted array, three-sum (fix one, two-pointer the rest), container with most water, trapping rain water.
- 2Two pointer technique โ fast/slow (Floyd's algorithm): one pointer moves one step at a time, the other moves two. If there's a cycle, they will meet inside it. Used to detect cycles in linked lists, find the middle of a linked list (stop when fast reaches end), and detect duplicate numbers in arrays. For finding the middle: when fast reaches the end, slow is at the middle โ useful for merge sort and palindrome checking.
- 3Sliding window โ fixed size: maintain a window of exactly k elements. To slide: add the new right element, subtract the old left element. Example: maximum sum subarray of size k โ compute the sum of the first k elements, then slide right and update in O(1) per step. Total O(n). Template: initialize window sum for first k elements; for i from k to n: sum += arr[i] - arr[i-k]; update result.
- 4Sliding window โ variable size: expand right pointer until the window is invalid; shrink from the left until valid again. Example: smallest subarray with sum โฅ target. Right pointer always moves forward (n times total). Left pointer also only moves forward (n times total). Total O(n) โ not O(nยฒ) even though there's a nested while loop, because each pointer traverses the array at most once. Template: left=0, result=inf; for right in range(n): add arr[right]; while window invalid: subtract arr[left], left++; update result.
- 5Prefix sums: precompute prefix[i] = arr[0] + arr[1] + ... + arr[i-1]. Then sum(arr[l..r]) = prefix[r+1] - prefix[l] in O(1). Build prefix in O(n), answer each range sum query in O(1). Extension: 2D prefix sums for matrix region sum queries. Critical use case: subarray sum equals k โ for each right index, check how many left indices have prefix[right] - prefix[left] = k, equivalently prefix[right] - k has been seen before. Use a hashmap of {prefix_sum: count}.
- 6Kadane's algorithm for maximum subarray: the key insight is: the maximum subarray ending at index i either (a) extends the maximum subarray ending at i-1, or (b) starts fresh at i. So: current_max = max(arr[i], current_max + arr[i]). Global max = max over all i of current_max. O(n) time, O(1) space. Handles negative numbers correctly. Variation: maximum product subarray requires tracking both max and min (because negative ร negative = positive).
- 7In-place array manipulation: many problems ask you to modify an array without extra space. Common techniques: (1) Use the array values as indices to mark visited positions (negation trick): if arr[abs(arr[i])-1] > 0, negate it to mark that value i was seen. (2) Two pointers for removing duplicates: keep a 'write pointer' that only advances when a new unique element is found. (3) Dutch National Flag (3-way partition): three pointers for values 0, 1, 2 โ sort in a single pass. (4) Rotation: reverse subarrays โ reverse whole array, reverse first k, reverse last n-k.
Key Patterns & Templates
Worked Examples
Given strings s and t, return the minimum window in s that contains all characters of t. Return '' if no window exists.
Common Mistakes
Off-by-one in window size: for a fixed window of size k, the window [i-k+1, i] starts being valid when i >= k-1. Write 'if i >= k-1: record result' not 'if i >= k'. Test with k=1 (every element is a valid window of size 1).
Forgetting to skip duplicates in 3Sum: after finding a valid triplet, advance both pointers AND skip duplicates. 'while left < right and nums[left] == nums[left+1]: left += 1' THEN 'left += 1'. Same for right. Otherwise you get duplicate triplets in output.
Not initializing the prefix sum hashmap with {0: 1}: for subarray sum problems, prefix[0] = 0 represents the empty subarray. Without this initialization, you miss subarrays that start from index 0. Classic bug: 'why is my answer off by the count of subarrays starting at 0?'
Dutch National Flag: not incrementing mid when swapping with hi: after swapping nums[mid] with nums[hi], decrement hi but DO NOT increment mid โ the newly swapped value at nums[mid] hasn't been examined yet. This is the most common bug in the 3-way partition.
Treating the variable sliding window while-loop as O(nยฒ): beginners see a while loop inside a for loop and assume O(nยฒ). The correct analysis: left and right each traverse the array exactly once โ right from 0 to n-1 (n steps), left from 0 to at most n-1 (at most n total steps). Total 2n = O(n). This amortized analysis is important to explain in interviews.