LeetCopilot Logo
LeetCopilot
LeetCode Pattern/Greedy Algorithm/Greedy Two-Pointer Pattern: When Greedy Meets Two Pointers (Template and Examples)

Greedy Two-Pointer Pattern: When Greedy Meets Two Pointers (Template and Examples)

LeetCopilot Team
Dec 30, 2025
10 min read
Greedy AlgorithmTwo PointersSortingMatchingInterview Prep
Learn the hybrid greedy + two-pointer pattern. Master the template for matching and pairing problems with complete examples.

The greedy two-pointer pattern combines two powerful techniques: greedy sorting + two-pointer matching.

This hybrid approach solves a specific class of problems where you need to pair or match elements optimally.

TL;DR

Pattern: Sort both arrays, use two pointers to greedily match elements.

When to use: Matching, pairing, assignment problems with constraints.

Template:

python
arr1.sort()
arr2.sort()

i = j = 0
while i < len(arr1) and j < len(arr2):
    if can_match(arr1[i], arr2[j]):
        i += 1
        j += 1
    else:
        j += 1  # Or i += 1

Time: O(n log n), Space: O(1)

The Core Idea

Why combine greedy + two pointers?

  1. Greedy: Sorting establishes optimal order
  2. Two pointers: Efficiently find matches in sorted arrays

Key insight: After sorting, you can make greedy decisions by comparing elements at pointer positions.

Pattern Variants

Variant 1: Same Direction (Both Increasing)

Use when: Matching elements from two arrays.

python
def match_elements(arr1, arr2):
    arr1.sort()
    arr2.sort()
    
    i = j = 0
    matches = 0
    
    while i < len(arr1) and j < len(arr2):
        if arr2[j] >= arr1[i]:  # Can match
            matches += 1
            i += 1
            j += 1
        else:
            j += 1  # Try next element in arr2
    
    return matches

Example: Assign Cookies (LC #455)

Variant 2: Opposite Direction (Left + Right)

Use when: Pairing elements from same array.

python
def pair_elements(arr, limit):
    arr.sort()
    
    left = 0
    right = len(arr) - 1
    pairs = 0
    
    while left < right:
        if arr[left] + arr[right] <= limit:
            pairs += 1
            left += 1
            right -= 1
        else:
            right -= 1  # Try smaller element
    
    return pairs

Example: Boats to Save People (LC #881)

Example 1: Boats to Save People

Problem: Each boat holds at most 2 people and has weight limit. Find minimum boats needed.

Greedy insight: Pair heaviest with lightest if possible.

python
def numRescueBoats(people, limit):
    """
    Time: O(n log n), Space: O(1)
    """
    people.sort()
    
    left = 0
    right = len(people) - 1
    boats = 0
    
    while left <= right:
        # Try to pair heaviest with lightest
        if people[left] + people[right] <= limit:
            left += 1   # Lightest person gets on
            right -= 1  # Heaviest person gets on
        else:
            right -= 1  # Heaviest goes alone
        
        boats += 1
    
    return boats

Why it works:

  • Heaviest person must go on a boat
  • If they can pair with lightest, that's optimal
  • If not, they go alone (no better option)

Trace:

code
people = [3, 2, 2, 1], limit = 3

After sort: [1, 2, 2, 3]

Step 1: left=0, right=3
  people[0]=1, people[3]=3
  1 + 3 = 4 > 3? YES
  Heaviest (3) goes alone
  boats=1, right=2

Step 2: left=0, right=2
  people[0]=1, people[2]=2
  1 + 2 = 3 <= 3? YES
  Pair them
  boats=2, left=1, right=1

Step 3: left=1, right=1
  Same person, goes alone
  boats=3

Result: 3 boats

Example 2: Two City Scheduling

Problem: 2n people, costs to send to city A or B. Send n to each city, minimize total cost.

Greedy insight: Sort by difference (cost_A - cost_B), send first n to A, rest to B.

python
def twoCitySchedCost(costs):
    """
    Time: O(n log n), Space: O(1)
    """
    # Sort by difference: how much we save by going to A
    costs.sort(key=lambda x: x[0] - x[1])
    
    total = 0
    n = len(costs) // 2
    
    # First n go to city A (biggest savings)
    for i in range(n):
        total += costs[i][0]
    
    # Last n go to city B
    for i in range(n, 2 * n):
        total += costs[i][1]
    
    return total

Why it works:

  • Sorting by difference identifies who benefits most from city A
  • Greedy: send those with biggest A-savings to A
  • Two-pointer-like: split sorted array in half

Example 3: Advantage Shuffle

Problem: Rearrange arr1 to maximize number of positions where arr1[i] > arr2[i].

Greedy insight: Match smallest arr1 that beats arr2[i], or use smallest arr1 if can't beat.

python
from collections import deque

def advantageCount(nums1, nums2):
    """
    Time: O(n log n), Space: O(n)
    """
    nums1.sort()
    
    # Create (value, index) pairs and sort by value
    sorted_nums2 = sorted((val, i) for i, val in enumerate(nums2))
    
    result = [0] * len(nums1)
    left = 0
    right = len(nums1) - 1
    
    # Process nums2 from largest to smallest
    for val, idx in reversed(sorted_nums2):
        if nums1[right] > val:
            # Can beat it, use largest available
            result[idx] = nums1[right]
            right -= 1
        else:
            # Can't beat it, use smallest (waste it)
            result[idx] = nums1[left]
            left += 1
    
    return result

Why it works:

  • For largest nums2 values, try to beat with largest nums1
  • If can't beat, waste smallest nums1 (save larger for later)
  • Two pointers track available nums1 elements

The Universal Template

python
def greedy_two_pointer(arr1, arr2, condition):
    """
    Universal template for greedy + two pointer.
    """
    # Step 1: Sort (greedy ordering)
    arr1.sort()
    arr2.sort()  # If needed
    
    # Step 2: Initialize pointers
    left = 0
    right = len(arr1) - 1  # Or use two arrays
    result = 0
    
    # Step 3: Two-pointer logic
    while left <= right:  # Or other condition
        if condition(arr1[left], arr1[right]):
            # Make greedy choice
            result += 1
            left += 1
            right -= 1
        else:
            # Adjust pointers
            right -= 1  # Or left += 1
    
    return result

When to Use This Pattern

Use greedy + two pointers when:

  • ✅ Need to match/pair elements
  • ✅ Optimal pairing depends on relative ordering
  • ✅ Can make greedy decision after sorting
  • ✅ Each element used at most once

Don't use when:

  • ❌ Order doesn't matter
  • ❌ Need to consider all pairs (use DP)
  • ❌ Elements can be reused

Common Mistakes

Mistake 1: Wrong Sort Direction

Wrong:

python
arr.sort(reverse=True)  # Descending when need ascending

Correct:

python
arr.sort()  # Ascending for greedy matching

Mistake 2: Moving Both Pointers Always

Wrong:

python
left += 1
right -= 1  # Always move both

Correct:

python
if condition:
    left += 1
    right -= 1
else:
    right -= 1  # Only move one

Mistake 3: Not Sorting First

Wrong:

python
# Forgot to sort!
left, right = 0, len(arr) - 1

Correct:

python
arr.sort()  # Must sort first
left, right = 0, len(arr) - 1

Complexity Analysis

Time Complexity:

  • Sort: O(n log n)
  • Two-pointer scan: O(n)
  • Total: O(n log n)

Space Complexity:

  • Sorting: O(1) if in-place
  • Pointers: O(1)
  • Total: O(1)

Practice these:

  1. Assign Cookies (LC #455) - Same direction matching
  2. Boats to Save People (LC #881) - Opposite direction pairing
  3. Two City Scheduling (LC #1029) - Sort by difference
  4. Advantage Shuffle (LC #870) - Strategic matching
  5. Minimum Number of Arrows (LC #452) - Interval merging variant

Decision Tree: Which Variant?

code
Need to match elements?
├─ From two arrays?
│  └─ Use same-direction (i, j)
│     Example: Assign Cookies
│
└─ From same array?
   └─ Use opposite-direction (left, right)
      Example: Boats to Save People

Conclusion

The greedy + two-pointer pattern is powerful for matching and pairing problems:

Key steps:

  1. Sort to establish greedy order
  2. Initialize pointers (same or opposite direction)
  3. Match greedily based on sorted order
  4. Move pointers based on match result

Remember: Sorting enables greedy decisions, two pointers enable efficient matching.

For more patterns, see Greedy with Sorting Template and the complete greedy guide.

Want to Practice LeetCode Smarter?

LeetCopilot is a free browser extension that enhances your LeetCode practice with AI-powered hints, personalized study notes, and realistic mock interviews — all designed to accelerate your coding interview preparation.

Also compatible with Edge, Brave, and Opera

Related Tutorials