Home > Back-end >  how does the two-pointer technique eliminate the need to check every element with every element?
how does the two-pointer technique eliminate the need to check every element with every element?

Time:01-08

I was solving a coding problem where:

You are given an integer array height of length n. There are n vertical lines drawn such that the two endpoints of the ith line are (i, 0) and (i, height[i]).

Find two lines that together with the x-axis form a container, such that the container contains the most water.

Return the maximum amount of water a container can store.

https://leetcode.com/problems/container-with-most-water/description/

My answer used brute force but the suggested answer with a time complexity of O(n) was this:

var maxArea = function (height) {
  let biggestArea = Number.MIN_VALUE;
  let leftPointer = 0;
  let rightPointer = height.length - 1;

  while (leftPointer < rightPointer) {
    let leftHeight = height[leftPointer];
    let rightHeight = height[rightPointer];
    let heightToUse = leftHeight < rightHeight ? leftHeight : rightHeight;
    let area = heightToUse * (rightPointer - leftPointer);
    biggestArea = Math.max(biggestArea, area);

    if (leftHeight < rightHeight) {
      leftPointer  ;
    } else {
      rightPointer--;
    }
  }

  return biggestArea;
};

I understand how this solution works but I still dont understand how the two-pointer technique eliminates the need to check every element with every element. could someone please explain the logic behind it? thank you.

CodePudding user response:

how the two-pointer technique eliminates the need to check every element with every element

When you have a pair (leftPointer, rightPointer), then the least of height[leftPointer] and height[rightPointer] determines the volume that the corresponding container has.

Let's assume that height[leftPointer] is the lesser one (or at least not greater).

Then we know that for any i in the range [leftPointer 1, ..., highPointer] the volume between leftPointer and i cannot be greater than what we already have. Even if there would be a very high height[i] it wouldn't matter as then height[leftPointer] is the lesser and determining height. And because the distance between leftPointer and i is less than the distance between leftPointer and rightPointer, the volume can never exceed what we already have.

So we don't need to visit those leftPointer, i pairs. That's were we avoid making all combinations.

On the other hand, we cannot exclude that there is an i where the i, highPointer pair would represent a greater volume container. That is why leftPointer is the correct action to take, and then the same reasoning can be applied to the new pair.

  • Related