Table of Contents
Task
Given n
non-negative integers a
1, a
2, ..., a
n , where each represents a point at coordinate (i, a
i)
. n
vertical lines are drawn such that the two endpoints of the line i
is at (i, a
i)
and (i, 0)
. Find two lines, which, together with the x-axis forms a container, such that the container contains the most water.
Notice that you may not slant the container.
Example 1:
Input:
height = [1,8,6,2,5,4,8,3,7]
Output:
49
Explanation:
The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.
Example 2:
Input:
height = [1,1]
Output:
1
Example 3:
Input:
height = [4,3,2,1,4]
Output:
16
Example 4:
Input:
height = [1,2,1]
Output:
2
This problem was taken from Leetcode Container With Most Water
Solution
A better than brute force solution is to use a variation of “sliding doors” algorithm.
Let’s consider this case: [1,3,4,3]. The area with most water will be the one with highest height and length.
To find it we set up two pointers: one at position 0, and one at the end of the array. The amount of water that could be collected here is min(leftPointerValue, rightPointerValue) * length,
where length is rightPointer – leftPointer. Which is 4.
Now it’s clear that if rightPointerValue > leftPointerValue there is no point of keep moving rightPointer because we won’t get any bigger amount of water since it will always be limited by the leftPointerValue (height) and the length will always be smaller than the previous length.
So in this case we will move the leftPointer forward to evaluate the next case.
Here the amount of the water collected is min(leftPointerValue, rightPointerValue) * length which is min(3, 3) * 3 = 9.
Nex we continue evaluating all cases till leftPointer = rightPointer (length = 0), and we didn’t find bigger amount of water collected, so the answer we found on the second evaluation is the right answer: 9.
/** * @param {number[]} height * @return {number} */ var maxArea = function(height) { var maxArea = 0; var pLeft = 0; var pRight = height.length - 1; var len = pRight - pLeft; while(len > 0) { var pLeftVal = height[pLeft]; var pRightVal = height[pRight]; if(pLeftVal > pRightVal) { maxArea = Math.max( len * pRightVal, maxArea ); pRight --; } else { maxArea = Math.max( len * pLeftVal, maxArea ); pLeft ++; } len --; } return maxArea; }; var height = [1,8,6,2,5,4,8,3,7]; console.log( maxArea(height) );