给定n个数: a1, a2, ... , an. 代表着(i, ai)个点, 连接这些点与对应的(i, 0), 我们可以得到n条线. 请在这n条线中找出2条, 使得这两条线和x轴构成的容器能够容纳最多的水.
本题解法时间复杂度为O(n), 作者是n00tc0d3r.
我们使用2个指针从数组前后开始遍历, 每次循环都计算一次最大值.
当左侧的数比右侧的数小时, 左指针向右挪动一格, 否则, 右指针向左挪动一格.
直到两个指针相遇, 算法结束.
1 class Solution { 2 public: 3 int maxArea(vector<int> &height) { 4 if (height.size() < 2) return 0; 5 int maxA = 0; 6 int low = 0, high = height.size() - 1; 7 while (low < high) { 8 int A = (high - low) * min(height[low], height[high]); 9 maxA = max(A, maxA); 10 if (height[low] < height[high]) 11 low++; 12 else 13 high--; 14 } 15 return maxA; 16 } 17 };
数学证明, 我们使用反证法:
假设返回值并非最优解.
由假设可得, 必定存在最优解.
假设这个最优解的边界是 aol 和 aor (分别代表左和右). 因为算法仅在两指针相遇时才终止. 所以算法必定访问到某个值的同时没有访问到另一个值.
不失一般性地, 可以假设low访问到了aol, 但high没有访问到aor.
当low指向aol的时候, 它以下条件不满足时不会移动:
- high也指向aol. 在这种情况下, 迭代终止了. 但另一个指针在它从右端移动的过程中一定访问过了aor. 矛盾.
- high指向某个值, 假设为 arr, 在high到达aor之前(arr为何一定在aor右侧? 因为如果arr在aor左侧, 那么就另一种假设[high访问到了aor而low没有访问到aol]就成立了), arr比aol大(否则我们就会移动high指针, 如果一直不满足这个条件, 最终high会指向aor, 矛盾). 这种情况下, 我们会移动low. 但是此时aol和arr的容积已经大于aol和aor的了(因为更宽), 这意味着aol 和aor并非最优解. 矛盾.
综上, 算法返回值必定是最优解.
英文原版说明:
[Suppose the returned result is not the optimal solution. Then there must exist an optimal solution, say a container with aol and aor (left and right respectively), such that it has a greater volume than the one we got. Since our algorithm stops only if the two pointers meet. So, we must have visited one of them but not the other. WLOG, let‘s say we visited aol but not aor. When a pointer stops at a_ol, it won‘t move until
- The other pointer also points to aol. In this case, iteration ends. But the other pointer must have visited aor on its way from right end to aol. Contradiction to our assumption that we didn‘t visit aor.
- The other pointer arrives at a value, say arr, that is greater than aol before it reaches aor. In this case, we does move aol. But notice that the volume of aol and arr is already greater than aol and aor (as it is wider and heigher), which means that aol and aor is not the optimal solution -- Contradiction!
Both cases arrive at a contradiction.]
[LeetCode系列]最大容器问题