Module 2: Two Pointers & Sliding Window·Tutorial 4 of 23 (Step 2.1)
All Tutorials·DSA Roadmap·18 Problems · ~10 hrs

2.1 Two Pointers

Understand what a Pointer index is, why Two Pointers eliminates O(N^2) nested loops using O(1) memory, and master opposite-end, read/write, and 3-way pointers.

01 Read the story: What & Why
02 Follow the drawing: Visual stepper
03 Practice code: 4 languages + problems
Lessons in this module:2.1 Two Pointers2.2 Sliding Window

1. What Is the Two Pointers Technique?

In array problems, a "pointer" is simply an integer variable (like left = 0 or right = n - 1) that remembers a position in the array.

Instead of using a single loop variable i (which only looks at one spot at a time) or two nested loops for i ... for j ... (which blindly checks every pair in O(N^2) time), Two Pointers places two coordinated bookmarks in the array and moves them using a smart rule so each element is visited at most once (O(N) time) with O(1) extra space.


2. Why Do We Need Two Pointers & How Do the 3 Flavors Work?

Flavor 1: Opposite-End Pointers (left = 0, right = n - 1)

Suppose you have a sorted list [2, 5, 8, 12, 30, 45] and want two numbers that add up to 35. If you stand at left = 0 (2) and right = 5 (45):

  • 2 + 45 = 47 (too big!). Since 2 is already the smallest number in the list, 45 added to anything else will be even bigger than 47. We can permanently cross out 45 (right -= 1)!
  • Now 2 + 30 = 32 (too small!). Since 30 is the largest remaining number, 2 is too small for everything else. Cross out 2 (left += 1)!
  • Now 5 + 30 = 35 — found in 3 steps instead of N^2!
Visual: Opposite-End Pointers Converging Inward on Sorted Array (Target = 35)
258123045left (L) ──►◄── right (R)Sum too small? Move L right (L++) | Sum too big? Move R left (R--)

Flavor 2: Same-Direction Read / Write Pointers (write = 0, read = 0)

When you need to filter or compact an array in-place (like removing duplicates or moving zeroes to the end), calling nums.pop(i) shifts the whole array (O(N^2)). Instead, read scans every element while write marks the next clean slot. Whenever read finds a keeper, copy nums[read] to nums[write] and step write += 1.

Visual: Same-Direction Read / Write Pointers (In-Place Compaction)
122030write (slow) ▼read (fast) ▼Everything left of write is clean! When read finds a valid item, copy it to nums[write++].

Flavor 3: Three-Way Partitioning (low, mid, high)

When sorting an array with only 3 distinct values (0, 1, 2 in Sort Colors), keep 0s before low, 1s between low and mid, and 2s after high.

Visual: 3-Way Partitioning Zones (Dutch National Flag)
0s [0 .. low-1]1s [low .. mid-1]? [mid .. high]2s [high+1 .. n-1]Goal: Shrink the unknown [mid..high] region until mid > high!

Step Through the Visual Drawing: Converging Two Pointers

Click Next below to see why moving left++ or right-- eliminates an entire row of pairs in O(1) time:

The Hand-Drawn Step-by-Step Walkthrough
Step 1 / 3

Interactive Step-by-Step Trace: Sorted Two Sum with Converging Pointers

Find two numbers in sorted [1, 3, 4, 6, 9] that sum to Target = 9:

Step 1: Compare Left (1) + Right (9) = 10 (Too Big!)
idx 01L
idx 13
idx 24
idx 36
idx 49R
sum = 1 + 9 = 10 > 9 -> Sum is too large, so decrement right--

Since 1 + 9 is already > 9, 9 + anything larger than 1 is also > 9. Eliminate 9!

✎ Remember this: Each comparison eliminates an entire row or column of pairs in O(1) time.

3. Basic Operations & Walkthroughs (All 4 Languages)

# 1. Opposite-End Pointers: Valid Palindrome / Sorted Two-Sum
def two_sum_sorted(nums: list[int], target: int) -> list[int]:
  left, right = 0, len(nums) - 1
  while left < right:
      s = nums[left] + nums[right]
      if s == target:
          return [left + 1, right + 1]
      elif s < target:
          left += 1
      else:
          right -= 1
  return []

# 2. Same-Direction Read/Write: Remove Duplicates from Sorted Array
def remove_duplicates(nums: list[int]) -> int:
  write = 1
  for read in range(1, len(nums)):
      if nums[read] != nums[write - 1]:
          nums[write] = nums[read]
          write += 1
  return write

# 3. Three-Way Partitioning (Sort Colors 0, 1, 2)
def sort_colors(nums: list[int]) -> None:
  low, mid, high = 0, 0, len(nums) - 1
  while mid <= high:
      if nums[mid] == 0:
          nums[low], nums[mid] = nums[mid], nums[low]
          low += 1; mid += 1
      elif nums[mid] == 1:
          mid += 1
      else:
          nums[mid], nums[high] = nums[high], nums[mid]
          high -= 1

4. Core Interview Patterns & Common Traps

Pattern: 3Sum & Container With Most Water (Converging Two Pointers)

Use when searching for pairs/triplets in sorted data or optimizing a width * min(height) objective from outer boundaries inward.

nums.sort()
for i in range(len(nums) - 2):
  if i > 0 and nums[i] == nums[i - 1]:
      continue  # Skip duplicate anchor
  l, r = i + 1, len(nums) - 1
  while l < r:
      s = nums[i] + nums[l] + nums[r]
      if s == 0:
          res.append([nums[i], nums[l], nums[r]])
          l += 1; r -= 1
          while l < r and nums[l] == nums[l - 1]: l += 1
      elif s < 0: l += 1
      else: r -= 1
Operation / PatternTimeSpaceNotes
Opposite-End Pointers (Already Sorted)O(N)O(1)Each step moves L right or R left
3Sum (Sort + Fix i + Two Pointers)O(N^2)O(1) auxSkip duplicate values of i, L, and R
Read / Write In-Place CompactionO(N)O(1)Preserves relative order of kept elements
Dutch National Flag (3-Way Partition)O(N)O(1)Single pass; do not advance mid when swapping with high

5. Practice On Your Own (Curated Submodule Problems)

0 / 18 Solved
StatusProblemDifficultyComplexityHint?Links & Notes
Valid Palindrome
Opposite-End Converging Pointers
Easy
T: O(N)
S: O(1)
Solve
Two Sum II - Input Array Is Sorted
Opposite-End Converging Pointers
Medium
T: O(N)
S: O(1)
Solve
3Sum
Opposite-End Converging Pointers
Medium
T: O(N^2)
S: O(1) aux
Solve
4Sum
Opposite-End Converging Pointers
Medium
T: O(N^3)
S: O(1) aux
Solve
Container With Most Water
Opposite-End Converging Pointers
Medium
T: O(N)
S: O(1)
Solve
Trapping Rain Water
Opposite-End Converging Pointers
Hard
T: O(N)
S: O(1)
Solve
Squares of a Sorted Array
Opposite-End Converging Pointers
Easy
T: O(N)
S: O(N)
Solve
Valid Palindrome II
Opposite-End Converging Pointers
Easy
T: O(N)
S: O(1)
Solve
Boats to Save People
Opposite-End Converging Pointers
Medium
T: O(N log N)
S: O(1)
Solve
Remove Duplicates from Sorted Array
Same-Direction Read/Write Pointers
Easy
T: O(N)
S: O(1)
Solve
Remove Duplicates from Sorted Array II
Same-Direction Read/Write Pointers
Medium
T: O(N)
S: O(1)
Solve
Move Zeroes
Same-Direction Read/Write Pointers
Easy
T: O(N)
S: O(1)
Solve
Merge Sorted Array
Same-Direction Read/Write Pointers
Easy
T: O(M + N)
S: O(1)
Solve
Is Subsequence
Same-Direction Read/Write Pointers
Easy
T: O(N)
S: O(1)
Solve
Sort Colors
Three-Way Partitioning (Dutch National Flag)
Medium
T: O(N)
S: O(1)
Solve
Next Permutation
Three-Way Partitioning (Dutch National Flag)
Medium
T: O(N)
S: O(1)
Solve
Rearrange Array Elements by Sign
Three-Way Partitioning (Dutch National Flag)
Medium
T: O(N)
S: O(N)
Solve
Rotate Array
Three-Way Partitioning (Dutch National Flag)
Medium
T: O(N)
S: O(1)
Solve