Skip to Content
Course content

233: Whiteboard Practice: Two-Pointer Techniques

Click on the "Edit" button in the top corner of the screen to edit your slide content.

When you're in a technical interview and the interviewer hands you a sorted array, your brain should immediately start tingling. "Sorted" is a massive hint. It means there is an inherent order we can exploit so we don't have to look at every single possible combination of elements.

Let's look at a classic whiteboard problem: we have a sorted array of integers, and we need to find if any two numbers add up to a specific target sum. If they do, we return their indices.

The brute-force instinct

If I'm thinking quickly, my first instinct is usually just to check everything. I'll grab the first number, then loop through every other number to see if they hit the target. Then I'll move to the second number and repeat. It looks like this:

const twoSumBrute = (nums, target) => {
  for (let i = 0; i < nums.length; i++) {
    for (let j = i + 1; j < nums.length; j++) {
      if (nums[i] + nums[j] === target) {
        return [i, j];
      }
    }
  }
  return null;
};

const numbers = [2, 7, 11, 15];
const target = 9;
console.log(twoSumBrute(numbers, target)); // [0, 1]

This works. But it's slow. If the array has 10,000 elements, I'm potentially doing millions of additions. I'm ignoring the most important piece of information I was given: the array is already sorted. In a real interview, this is where the interviewer would ask, "Can we do this in linear time?"

Noticing the sorted advantage

Let's think about how we'd do this by hand. If I have [2, 7, 11, 15] and my target is 22, I wouldn't start at the beginning and just guess. I'd probably look at the biggest number (15) and the smallest number (2).

15 + 2 is 17. That's too small. Since the array is sorted, I know that 2 is the smallest possible value. Adding 2 to anything else isn't going to help me get closer to 22 than adding something larger than 2 would. So, I can effectively "discard" the 2 and move inward.

Wait, let's try that in code. Instead of nested loops, I'll use two variables to keep track of my positions—one at the start and one at the end.

Squeezing the array from both sides

I'll call these left and right. I'll move them toward each other based on whether my current sum is too high or too low. It's almost like a game of "Hot or Cold."

const twoSumTwoPointer = (nums, target) => {
  let left = 0;
  let right = nums.length - 1;

  while (left < right) {
    const currentSum = nums[left] + nums[right];

    if (currentSum === target) {
      return [left, right]; // Found it!
    }

    if (currentSum < target) {
      // Sum is too small, we need a larger number.
      // Since it's sorted, moving 'left' to the right increases the sum.
      left++;
    } else {
      // Sum is too large, we need a smaller number.
      // Moving 'right' to the left decreases the sum.
      right--;
    }
  }

  return null; // No pair found
};

const numbers = [2, 7, 11, 15];
const target = 26; 
console.log(twoSumTwoPointer(numbers, target)); // [2, 3] (11 + 15)

I love this approach because it's clean. I'm not guessing; I'm making a logical decision at every single step. If the sum is too low, the only way to increase it is to move the left pointer up. If it's too high, the only way to decrease it is to move the right pointer down.

Why this actually saves us time

In the first version, I had a loop inside a loop. That's $O(n^2)$ time complexity. In this version, I have one while loop. In the absolute worst case, the pointers meet in the middle, meaning I've looked at each element at most once. That's $O(n)$—linear time.

Two-pointer techniques aren't just for summing numbers, though. You'll see this pattern whenever you're dealing with sorted lists, reversing strings, or even detecting cycles in linked lists. The core idea is always the same: use two indices to narrow down the search space without having to re-scan the entire collection.




📋 Practical Task

Exercise: Valid Palindrome Scanner

In this exercise, you'll apply the two-pointer technique to determine if a string is a palindrome (reads the same forwards and backwards). However, there's a catch: the string might contain spaces, punctuation, and mixed casing, which should all be ignored.

Your Task: Write a function isPalindrome(str) that:

  • Uses two pointers (one at the start, one at the end) to compare characters.
  • Skips any non-alphanumeric characters.
  • Is case-insensitive.
  • Returns true if it's a palindrome, otherwise false.

Test Case: isPalindrome("A man, a plan, a canal: Panama") should return true.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.