In my last post, I covered arrays and strings and briefly touched on the two-pointer technique while reversing an array. That one example ended up being the gateway to a much bigger pattern — one that quietly powers a huge chunk of interview problems.
Once you start noticing two pointers and sliding window, you can't unsee them. Let's break down what they actually are, how they differ, and when to reach for each one.
What is the two-pointer technique?
Two pointers means using two index variables to traverse a data structure, instead of one. The pointers can move:
- Towards each other (from opposite ends)
- In the same direction (one ahead of the other)
// Example: check if a sorted array has two numbers that add up to a target
boolean hasPairWithSum(int[] arr, int 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++; // need a bigger sum
else right--; // need a smaller sum
}
return false;
}
💡 This only works because the array is sorted. Sorting first (if it isn't already) is a common setup step for two-pointer problems.
The magic here is that instead of checking every pair (O(n²)), we eliminate one possibility per step, bringing it down to O(n).
Same-direction two pointers
Not all two-pointer problems move towards each other. Sometimes both pointers move forward, with one acting as a "slow" tracker and the other as a "fast" scanner.
// Remove duplicates from a sorted array, in place
int removeDuplicates(int[] arr) {
if (arr.length == 0) return 0;
int slow = 0;
for (int fast = 1; fast < arr.length; fast++) {
if (arr[fast] != arr[slow]) {
slow++;
arr[slow] = arr[fast];
}
}
return slow + 1; // new length
}
Here, slow marks the boundary of the "cleaned up" part of the array, while fast explores ahead. This pattern shows up in linked list problems too (like detecting cycles with slow/fast pointers).
What is the sliding window technique?
Sliding window is really a specialized form of two pointers, used when you're looking at contiguous subarrays or substrings. Instead of recalculating a sum/count from scratch for every window, you slide the window and adjust incrementally.
There are two flavors:
Fixed-size window
// Maximum sum of any subarray of size k
int maxSumSubarray(int[] arr, int k) {
int windowSum = 0;
for (int i = 0; i < k; i++) windowSum += arr[i];
int maxSum = windowSum;
for (int i = k; i < arr.length; i++) {
windowSum += arr[i] - arr[i - k]; // slide the window
maxSum = Math.max(maxSum, windowSum);
}
return maxSum;
}
Instead of recomputing the sum of every window from scratch (O(n·k)), we just add the new element and remove the old one — O(n) total.
Variable-size window
// Longest substring without repeating characters
int longestUniqueSubstring(String s) {
Set seen = new HashSet<>();
int left = 0, maxLen = 0;
for (int right = 0; right < s.length(); right++) {
while (seen.contains(s.charAt(right))) {
seen.remove(s.charAt(left));
left++;
}
seen.add(s.charAt(right));
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}
⚠️ The window only shrinks when a condition is violated (a repeat character, in this case). This "expand, then shrink when needed" shape is the core of every variable-size sliding window problem.
Two pointers vs sliding window — when to use which
| Situation | Technique |
|---|---|
| Sorted array, looking for a pair/triplet | Two pointers (opposite ends) |
| In-place modification, tracking a boundary | Two pointers (same direction) |
| Fixed-length contiguous subarray (size k) | Sliding window (fixed) |
| "Longest/shortest substring that satisfies X" | Sliding window (variable) |
| Need to compare elements from both ends | Two pointers |
A quick gut-check: if the problem mentions "subarray" or "substring", think sliding window first. If it mentions "pair," "sorted array," or "in-place," think two pointers.
A problem to try
Minimum size subarray sum: given an array of positive integers and a target sum, find the length of the smallest contiguous subarray whose sum is ≥ target. (Hint: variable-size sliding window — expand until the sum meets the target, then shrink from the left while it still does.)
Thanks for reading! Next up, I'll get into hashing and HashMaps — another pattern that pairs really well with sliding window for problems where you need to track frequency or seen elements. If two pointers finally clicked for you after this, drop a comment 🙌
Top comments (0)