11. Container With Most Water

Given n non-negative integers a1a2, ..., an, where each represents a point at coordinate (iai). n vertical lines are drawn such that the two endpoints of line i is at (iai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.

Note: You may not slant the container and n is at least 2.

问题:给出一组非负数组 a1a2, ..., an,ai表示位于位置i的线的高度,用任意两根线装水,求最大值,不能倾斜。

不能倾斜,装水,所以上述问题就是求   res = min(a[i], a[j]) * (j - i)  的最大值,其中 0 <= i < j <= n。

1、最简单最暴力的方法是遍历所有组合了,这样时间复杂度就是O(n2)。

2、想一个复杂度比较小的方法。要使乘积足够大,首先a[i], a[j]要足够大,其次两个数要足够远,也就是(j - i)足够大。从这个方向去解决问题:

设置两个指针,一个从头开始扫,一个从尾部开始,这样能保证(j - i)是最大的。在(j - i)减小的基础上,为了增大res, 需要增大min(a[i], a[j])。

不妨设 a[i] < a[j],所以 ++i, 只要找到a[i + m] > a[i],此时判断哪个面积更大,并在这个基础上继续扫描。

这边有一个问题,就是 假设  res1 = min(a[i], a[j]) * (j - i) < min(a[i + m], a[j]) * (j - i - m) = res2 ,

会不会存在一个n,使得 res3 = min(a[i], a[j - n]) * (j - i - n) > min(a[i + m], a[j]) * (j - i - m) = res2 

因为在上一步, res2 > res1 时,i ← i + m,那么如果存在这种情况,方法2就是不严谨的。

证明:

已知 1、ai<ai+m; 2、a< aj-n; 3、min(ai, aj) * (j - i) < min(ai+m, aj) * (j - i - m)

反证法: 假设存在n, 使res3 > res2

那么就有 res3 > res1

于是 min(ai, aj-n) > min(ai, aj)

情况1:aj-n > ai > aj, 或ai > aj-n > aj

那么可以推出     aj * (j - i)  = min(ai, aj) * (j - i)  > min(ai+m, aj) * (j - i - m) =  aj * (j - i - m) , 与已知条件3矛盾

情况2:aj > ai > aj-n   显然与已知条件2矛盾

 

那么就愉快地发现方法2是严谨的。时间复杂度成功降到O(n)

 1 class Solution {
 2 public:
 3     int maxArea(vector<int>& height) {
 4         if (height.empty())
 5             return 0;
 6         int low = 0;
 7         int high = height.size() - 1;
 8         int res = min(height[low], height[high]) * (high - low);
 9         while (low < high) {
10             if (height[low] < height[high]) {
11                 while (height[low + 1] <= height[low])
12                     ++low;
13                 res = max(res, min(height[++low], height[high]) * (high - low));
14             }  
15             else {
16                 while (height[high - 1] <= height[high])
17                     --high;
18                 res = max(res, min(height[low], height[--high]) * (high - low));
19             }
20         }
21         return res;
22     }
23 };

 

posted @ 2018-04-11 19:28  Zzz...y  阅读(123)  评论(0编辑  收藏  举报