Leetcode/Guide/Two Pointers

Last edited by dave on 08/11/2025, 16:01:02 UTC

Leetcode / Guide / Two Pointers

Contents

The Two Pointers technique is a simple yet powerful approach often used in coding tests. It helps you efficiently solve problems involving arrays or strings without using nested loops.

Instead of checking every possible pair (which is slow), you move two variables β€” or pointers β€” strategically through the data.


🧠 Concept Overview

  • You use two indices (or β€œpointers”) to track positions in an array or string.
  • Depending on the problem, pointers may:
    • Start at opposite ends and move toward each other.
    • Start at the same position and move forward at different speeds.

This technique helps you reduce time complexity from O(nΒ²) to O(n).


Example 1 β€” Palindrome Check (Array)

Use a while loop with two pointers, one from the start and one from the end.

function isArrayPalindrome(numbers) { let leftIndex = 0; let rightIndex = numbers.length - 1; while (leftIndex < rightIndex) { if (numbers[leftIndex] !== numbers[rightIndex]) { return false; } leftIndex++; rightIndex--; } return true; } // Demo console.log(isArrayPalindrome([1, 2, 3, 2, 1])); // true console.log(isArrayPalindrome([1, 2, 3])); // false

βœ… Why this works:
Both pointers move toward the center, comparing each mirrored pair. If any pair differs, it’s not a palindrome.


Example 2 β€” Two Sum (Sorted Array)

If an array is sorted, you can find two numbers that sum to a target in one pass.

function findTwoNumbersThatSumToTarget(sortedNumbers, targetSum) { let leftIndex = 0; let rightIndex = sortedNumbers.length - 1; while (leftIndex < rightIndex) { const currentSum = sortedNumbers[leftIndex] + sortedNumbers[rightIndex]; if (currentSum === targetSum) { return [sortedNumbers[leftIndex], sortedNumbers[rightIndex]]; } if (currentSum < targetSum) { leftIndex++; // need a larger sum } else { rightIndex--; // need a smaller sum } } return null; // no valid pair found } // Demo console.log(findTwoNumbersThatSumToTarget([1, 2, 3, 4, 6, 8, 9], 10)); // [2, 8]

βœ… Why this works:
Since the array is sorted, you can move pointers intelligently β€” avoiding unnecessary checks.


Example 3 β€” Remove Duplicates from a Sorted Array

Use two pointers with a for loop to overwrite duplicates efficiently.

function removeDuplicatesFromSortedArray(sortedNumbers) { if (sortedNumbers.length === 0) return 0; let uniqueWriteIndex = 0; for (let readIndex = 1; readIndex < sortedNumbers.length; readIndex++) { if (sortedNumbers[readIndex] !== sortedNumbers[uniqueWriteIndex]) { uniqueWriteIndex++; sortedNumbers[uniqueWriteIndex] = sortedNumbers[readIndex]; } } return uniqueWriteIndex + 1; // count of unique elements } // Demo const numbers = [1, 1, 2, 2, 3, 4, 4]; const uniqueCount = removeDuplicatesFromSortedArray(numbers); console.log(uniqueCount); // 4 console.log(numbers.slice(0, uniqueCount)); // [1, 2, 3, 4]

βœ… Why this works:
You only shift elements when you find a new unique value, keeping everything in place.


Example 4 β€” Reverse a String

Use a for loop and swap characters from both ends.

function reverseStringCharacters(inputText) { const characters = inputText.split(''); for ( let leftIndex = 0, rightIndex = characters.length - 1; leftIndex < rightIndex; leftIndex++, rightIndex-- ) { const tempChar = characters[leftIndex]; characters[leftIndex] = characters[rightIndex]; characters[rightIndex] = tempChar; } return characters.join(''); } // Demo console.log(reverseStringCharacters("hello")); // "olleh"

βœ… Why this works:
Both pointers move toward each other while swapping characters.


Example 5 β€” Sliding Window (Find Smallest Subarray β‰₯ Target)

Use a combination of for and while loops.

function findSmallestSubarrayLengthAtLeastTarget(numbers, targetSum) { let windowStart = 0; let currentSum = 0; let minLength = Infinity; for (let windowEnd = 0; windowEnd < numbers.length; windowEnd++) { currentSum += numbers[windowEnd]; while (currentSum >= targetSum) { const windowLength = windowEnd - windowStart + 1; minLength = Math.min(minLength, windowLength); currentSum -= numbers[windowStart]; windowStart++; } } return minLength === Infinity ? 0 : minLength; } // Demo console.log(findSmallestSubarrayLengthAtLeastTarget([2, 1, 5, 2, 3, 2], 7)); // 2 (subarray [5,2])

βœ… Why this works:
You expand and contract the β€œwindow” dynamically to keep the sum just above the target.


🧩 Summary Table

PatternDescriptionCommon Problems
Two Ends (Meet in Middle)Compare or combine elements from both sidesPalindrome, Reverse
Slow/Fast PointersSkip duplicates, detect cyclesDeduplication, Linked Lists
Sliding WindowDynamic range controlSubarray sum, unique characters

πŸš€ Key Takeaways

  • Two Pointers = less nesting, more efficiency
  • Works best with sorted arrays, strings, or linked lists
  • Reduces complexity from O(nΒ²) β†’ O(n)
  • Clear variable names like leftIndex, rightIndex, windowStart, and windowEnd make logic easy to follow during coding tests
Backlinks (1)
Categories (0)

    No categories assigned to this page.

Edit Level

> Signed In Users