Container With Most Water
You are given an integer array height of length n. 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.
- n == height.length
- 2 <= n <= 10⁵
- 0 <= height[i] <= 10^4
height = [1,8,6,2,5,4,8,3,7]49height = [1,1]1Finding the maximum volume of water a container can hold is fundamentally a challenge of balancing width against height. Since the container's volume is limited by its shortest wall, we need a strategy that effectively navigates the trade-offs between the distance between walls and their individual heights.
The most straightforward approach is to calculate the area for every possible pair of lines (i, j). We calculate width * height, where width is the distance between indices and height is the minimum of the two line heights. This approach involves a nested loop, leading to O(N²) time complexity, which is far too slow for large inputs where n can reach 100,000.
# Brute force: nested loops
def brute_force(height):
max_area = 0
for i in range(len(height)):
for j in range(i + 1, len(height)):
area = (j - i) * min(height[i], height[j])
max_area = max(max_area, area)
return max_areaThe true insight here is to start with the widest possible container and greedily work inward. Since the water level is limited by the shorter wall, moving the taller wall inward will always decrease the width without any chance of increasing the height bottleneck. Therefore, the only way to potentially find a larger area is to move the shorter wall inward, looking for a taller replacement.
We place two pointers at the absolute edges of the array. At each step, we calculate the area formed by the current walls and always move the pointer pointing to the shorter wall, as it is the current limiting factor. We keep track of the maximum area encountered, converging in O(N) because each step moves one of the pointers, ensuring we scan every wall exactly once.
# Optimal: two pointers
def max_area(height):
l, r, max_a = 0, len(height) - 1, 0
while l < r:
area = (r - l) * min(height[l], height[r])
max_a = max(max_a, area)
if height[l] < height[r]:
l += 1
else:
r -= 1
return max_aFluid Intuition
Geometric Optimization Trace
Key Insight
Area is strictly limited by the shorter wall. Moving the taller wall only decreases width without any possibility of a taller bottleneck.
Strategy
Always move the pointer pointing to the shorter line. It is the only way to potentially find a taller line to offset the width reduction.