When solving DSA problems, two pointers and sliding window can look almost identical in code.
Both often use variables like:
left = 0
right = 0
The difference is not really about how many pointers we use.
The important question is:
What do the pointers represent?
Two Pointers
Two pointers is a general technique where two indices move through a data structure to reduce unnecessary work.
A common example is finding two numbers in a sorted array whose sum equals a target.
left = 0
right = len(nums) - 1
while left < right:
total = nums[left] + nums[right]
if total == target:
return [left, right]
elif total < target:
left += 1
else:
right -= 1
Here, we mainly care about:
nums[left] and nums[right]
The elements between them do not represent anything important.
Common Two Pointer Patterns
Opposite Direction
L → ← R
Common in:
- Two Sum II
- Valid Palindrome
- Container With Most Water
- 3Sum
A strong clue is:
Sorted array + pair/target
Fast and Slow
slow → → →
fast → → → → → →
Common in:
- Linked List Cycle
- Middle of Linked List
- Happy Number
The pointers move at different speeds.
Read and Write
One pointer searches while another modifies the array.
write = 0
for read in range(len(nums)):
if nums[read] != 0:
nums[write] = nums[read]
write += 1
Common in:
- Move Zeroes
- Remove Duplicates
- In-place array modification
Sliding Window
Sliding window is a more specific form of the two-pointer technique.
Instead of caring only about the values at left and right, we care about the entire range between them.
L [...............] R
window
For example:
Find the longest substring without repeating characters.
left = 0
seen = set()
for right in range(len(s)):
while s[right] in seen:
seen.remove(s[left])
left += 1
seen.add(s[right])
The important part is the current window:
s[left:right + 1]
The Sliding Window Pattern
Most variable-sized sliding window problems follow this structure:
left = 0
for right in range(len(nums)):
# Add nums[right]
while window_is_invalid:
# Remove nums[left]
left += 1
# Update answer
The idea is:
expand → expand → invalid → shrink → expand
Fixed vs Variable Sliding Window
Fixed Window
The size is already given.
For example:
Find the maximum sum of
kconsecutive elements.
[2, 1, 5, 1, 3, 2]
[2 1 5]
[1 5 1]
[5 1 3]
[1 3 2]
Typical clues:
- size
k kconsecutive elements- average of every
kelements
Variable Window
The window changes depending on a condition.
For example:
Find the longest subarray with sum less than or equal to
k.
left = 0
current_sum = 0
for right in range(len(nums)):
current_sum += nums[right]
while current_sum > k:
current_sum -= nums[left]
left += 1
Typical clues:
- longest substring
- shortest subarray
- at most
k - no repeating characters
- maximum consecutive elements satisfying a condition
How to Differentiate Them
The easiest question to ask is:
Do I care about everything between the two pointers?
If yes:
L [ entire region matters ] R
Think Sliding Window.
If you mainly care about:
nums[L] and nums[R]
think Two Pointers.
Another Useful Difference
Two pointers often move because of the relationship between two values:
if nums[left] + nums[right] < target:
left += 1
else:
right -= 1
Sliding window moves because of the condition of the entire window:
while window_is_invalid:
left += 1
That distinction is usually more useful than looking at the code itself.
Recognition Cheat Sheet
| Problem Pattern | Technique |
|---|---|
| Sorted array + target pair | Two Pointers |
| Palindrome | Two Pointers |
| Linked list cycle | Fast/Slow Pointers |
| Remove/move elements in-place | Read/Write Pointers |
| Contiguous subarray/substring | Sliding Window |
| Longest/shortest valid range | Sliding Window |
k consecutive elements |
Fixed Sliding Window |
| Expand until invalid, then shrink | Variable Sliding Window |
What About Best Time to Buy and Sell Stock?
LeetCode 121 is sometimes implemented using variables such as:
buy = 0
sell = 1
which makes it look like a two-pointer or sliding-window problem.
But conceptually, the solution is:
min_price = float("inf")
max_profit = 0
for price in prices:
min_price = min(min_price, price)
max_profit = max(max_profit, price - min_price)
We are maintaining:
minimum price seen so far
rather than maintaining a real window.
So it is better understood as a greedy / minimum-so-far problem.
Final Mental Model
When you see an array or string problem, use this decision tree.
Do I need two positions?
|
v
YES
|
v
Is the answer based on a CONTIGUOUS RANGE?
|
YES / NO
/ \
v v
Sliding Two
Window Pointers
Then refine further.
If it looks like Two Pointers
Sorted array + target/pair?
↓
Opposite pointers
Remove/move/modify elements?
↓
Read/write pointers
Linked list cycle/middle?
↓
Fast/slow pointers
If it looks like Sliding Window
Fixed length k?
↓
Fixed sliding window
Longest/shortest satisfying constraint?
↓
Variable sliding window
You can also think of the relationship like this:
Two Pointers
/ \
Opposite Ends Same Direction
|
┌──────────┴──────────┐
| |
Sliding Window Read / Write
The most useful question to remember is:
What does the space between my pointers represent?
If that region itself is the thing you are analysing, you are probably dealing with a sliding window.
If the pointers simply represent two independent positions, you are probably dealing with a two-pointer problem.