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.
Notice that you may not slant the container.
solution
- we use two-pointers to move gradually inward from the outside, keeping track of most water stored in
ans. - we always move inward with the shorter of the two walls!
- we can prove this greedy approach by thinking about the contrary.
- if we moved in with the taller wall, we would always guarantee that our stored water would be less, because the horizontal distance is decreasing, and even if we found a taller wall, we would still be equally limited by the shorter wall (that we did not move inwards from).
- therefore, we must always move the shorter wall to have a chance at increasing
ans.
A good proof
This is a formal proof, beyond the simple greedy idea that “because a wall is no longer going to contribute, we can move past it.” That idea doesn’t adequately prove that we’re guaranteed to reach the global optima.
The correct solution has a left bound of and a right bound of with a height . At some point of this algorithm’s execution, the left pointer i or the right pointer will point to one of for the first time. Consider the case where and
Case 1: . The container is wider than . If was as tall as , then it would be bigger than . This is a contradiction, so this case is impossible.
Case 2: . Because , this implies that , so we will decrement . This brings us closer to the correct solution, .
We can repeatedly apply this same logic to every step to decrement j until we reach . At that point, the optimal solution will be recorded.
By symmetry, we are assured that when , then the same logic will allow us to increment to .
class Solution:
def maxArea(self, height: List[int]) -> int:
ans = 0
l, r = 0, len(height)-1
while l < r:
minheight = min(height[l], height[r])
ans = max(ans, minheight * (r-l))
# how do we move in? greedily keep the larger one
if height[l] < height[r]:
l += 1
else:
r -= 1
return ans