Lesson 20 of 164
Container With Most Water
Given n non-negative heights, where line i goes from (i, 0) to (i, height[i]), find two lines that form a container with the x-axis holding the most water. Return that amount. n is at least 2.
The water between lines i < j is limited by the shorter line: area = (j - i) * min(height[i], height[j]).
LeetCode: 11. Container With Most Water
Example
Input: [1, 8, 6, 2, 5, 4, 8, 3, 7]
Output: 49 (lines 1 and 8: width 7, height min(8, 7) = 7)Brute force: every pair
public class Main {
static int maxArea(int[] height) {
int best = 0;
for (int i = 0; i < height.length; i++) {
for (int j = i + 1; j < height.length; j++) {
best = Math.max(best, (j - i) * Math.min(height[i], height[j]));
}
}
return best;
}
public static void main(String[] args) {
System.out.println(maxArea(new int[]{1, 8, 6, 2, 5, 4, 8, 3, 7}));
System.out.println(maxArea(new int[]{1, 1}));
}
}49
1Time: O(n²). Space: O(1).
Optimal: two pointers, move the shorter line
Start with the widest container, i = 0 and j = n - 1. Suppose height[i] <= height[j]. Every other container that uses line i is narrower, and its height is still at most height[i], so none can beat the current one. Line i can be discarded: move i right. By the same argument, if height[j] is shorter, move j left. Each step discards one line, so the loop runs n - 1 times.
public class Main {
static int maxArea(int[] height) {
int i = 0, j = height.length - 1;
int best = 0;
while (i < j) {
int area = (j - i) * Math.min(height[i], height[j]);
best = Math.max(best, area);
if (height[i] <= height[j]) {
i++;
} else {
j--;
}
}
return best;
}
public static void main(String[] args) {
System.out.println(maxArea(new int[]{1, 8, 6, 2, 5, 4, 8, 3, 7}));
System.out.println(maxArea(new int[]{1, 1}));
System.out.println(maxArea(new int[]{4, 3, 2, 1, 4}));
}
}49
1
16Time: O(n). Space: O(1).
Edge cases
- Equal heights at both ends: moving either pointer is safe; neither line can form a larger container with anything in between.
- Large inputs:
width * heightis anintmultiplication and wraps silently pastInteger.MAX_VALUE. Compute the area as(long) (j - i) * Math.min(...)and keepbestas alongif the limits allow it.
