Loading problems...
TL;DR: The optimal solution utilizes a two-pointer approach starting from both ends of the array, iteratively moving the pointer pointing to the shorter line inward to maximize the potential area.
The "Container With Most Water" problem asks us to find two vertical lines within an array of line heights that, together with the x-axis, form a container capable of holding the maximum amount of water. The amount of water is determined by the area of the rectangle formed by the two lines. The height of this rectangle is limited by the shorter of the two lines, and the width is the distance between the indices of the lines.
This is a classic optimization problem found in LeetCode 11, often used in technical interviews to test understanding of greedy strategies and array manipulation.
The most intuitive way to solve this problem is to calculate the area for every possible pair of lines and keep track of the maximum area found.
maxArea to 0.i from 0 to n-1.j from to .i+1n-1(i, j), calculate the width as (j - i).min(height[i], height[j]).maxArea if the current area is larger.python# Pseudo-code for Brute Force max_area = 0 for i from 0 to n-1: for j from i+1 to n-1: current_area = min(height[i], height[j]) * (j - i) max_area = max(max_area, current_area) return max_area
Time Complexity: . We check pairs. Why it fails: The constraints state that can be up to . An solution results in approximately operations, which far exceeds the standard time limit (usually around operations per second). This leads to a Time Limit Exceeded (TLE) error on large test cases.
The key intuition relies on the formula for the area:
To maximize the area, we want both the width and the height to be as large as possible. We start with the maximum possible width by placing pointers at the first and last indices.
From this state, we must decide which pointer to move inward. The decision is driven by the "bottleneck" of the container. The water level is constrained by the shorter line.
Invariant: At every step, we can safely discard the shorter line because it cannot possibly form a larger area with any other line strictly inside the current window than it does with the current outer boundary.
Visual Description: Imagine the algorithm as a shrinking window. Initially, the window covers the entire array. We compare the values at the edges. If the left edge is lower than the right edge, we visually "cross out" the left indexβit has reached its maximum potential area with the furthest possible pair (the right edge). We then shift the left boundary to the right. Conversely, if the right edge is lower, we cross it out and shift the right boundary to the left. We repeat this until the window closes.

Let's trace the algorithm with the input height = [1, 8, 6, 2, 5, 4, 8, 3, 7].
Start: left = 0 (val 1), right = 8 (val 7).
height[left] < height[right]. Move left to 1.Step 2: left = 1 (val 8), right = 8 (val 7).
height[right] < height[left]. Move right to 7.Step 3: left = 1 (val 8), right = 7 (val 3).
height[right] < height[left]. Move right to 6.Step 4: left = 1 (val 8), right = 6 (val 8).
right to 5.Step 5: left = 1 (val 8), right = 5 (val 4).
height[right] < height[left]. Move right to 4.Step 6: left = 1 (val 8), right = 4 (val 5).
height[right] < height[left]. Move right to 3.Step 7: left = 1 (val 8), right = 3 (val 2).
height[right] < height[left]. Move right to 2.Step 8: left = 1 (val 8), right = 2 (val 6).
height[right] < height[left]. Move right to 1.End: left meets right. Return Max Area: 49.
To prove this greedy strategy works, consider the state where we have pointers at left and right, and assume height[left] < height[right].
The algorithm decides to move left to left + 1. This effectively discards all pairs (left, k) where left < k < right. Is it possible that one of these discarded pairs has a larger area than the current (left, right)?
(left, k) is k - left. Since k < right, the width k - left is strictly less than right - left.(left, k) is min(height[left], height[k]). This value can be at most height[left].(left, k) is at most height[left] * (k - left), which is strictly less than height[left] * (right - left).Thus, the pair (left, right) provides the maximum possible area involving the index left. We can safely discard left and narrow our search space without missing the global maximum.
cppclass Solution { public: int maxArea(vector<int>& height) { int left = 0; int right = height.size() - 1; int max_area = 0; while (left < right) { // Calculate current area int width = right - left; int current_height = min(height[left], height[right]); max_area = max(max_area, width * current_height); // Move the pointer corresponding to the shorter line if (height[left] < height[right]) { left++; } else { right--; } } return max_area; } };
javaclass Solution { public int maxArea(int[] height) { int left = 0; int right = height.length - 1; int maxArea = 0; while (left < right) { // Calculate current area int width = right - left; int currentHeight = Math.min(height[left], height[right]); maxArea = Math.max(maxArea, width * currentHeight); // Move the pointer corresponding to the shorter line if (height[left] < height[right]) { left++; } else { right--; } } return maxArea; } }
pythonclass Solution: def maxArea(self, height: List[int]) -> int: left = 0 right = len(height) - 1 max_area = 0 while left < right: # Calculate current area width = right - left current_height = min(height[left], height[right]) max_area = max(max_area, width * current_height) # Move the pointer corresponding to the shorter line if height[left] < height[right]: left += 1 else: right -= 1 return max_area
Time Complexity: The algorithm uses two pointers that start at opposite ends and move toward each other. Each element in the array is visited at most once. Therefore, the time complexity is linear with respect to the number of elements.
Space Complexity:
We only use a fixed number of variables (left, right, max_area) to maintain state. No auxiliary data structures proportional to the input size are used.
The Two Pointers - Converging pattern is a fundamental technique for optimizing array problems, particularly when searching for pairs or triplets that satisfy a condition. This pattern is directly applicable to:
Why does the naive solution result in TLE? The naive solution uses nested loops, resulting in complexity. With , this performs roughly operations, exceeding the typical execution time limit of 1-2 seconds.
Common Mistakes:
Moving the taller line instead of the shorter one:
Moving both pointers inward simultaneously:
left and decrementing right in the same iteration regardless of heights.height[left] is very small and height[right] is huge, moving right inward might discard the optimal partner for a future left value.Calculating area incorrectly:
max(height[left], height[right]) instead of min.