Container With Most Water(最大容器)

来源:互联网 发布:it系统集成课程 编辑:程序博客网 时间:2024/05/22 05:28

Given n non-negative integers a1, a2, …, an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.(给定n个非负整数a1,a2,…,an,每个整数代表一个坐标点(i,ai)。由(i,ai)和(i, 0)两点组成直线i,总共n条这样的垂直线。找出两条垂直线,并与x轴组成一个容器,使得能够容纳最多的水)

Note: You may not slant the container.(不能使容器倾倒)

1.个人分析
由题意可理解为,要找出两条垂直线使得与x轴组成的面积最大。如果两条垂直线不相等时,那么就取小的值作为容器面积的高。
思路:采用穷举法,求出所有可能值,找出最大值。

2.个人解法

int maxArea(vector<int>& height){    int maxArea = 0;    int len = height.size();    for(int i=0; i < len; ++i) {        for(int j=len-1; j >=0; --j) {            int curArea = (j - i) * min(height[i], height[j]);            if(curArea > maxArea)                maxArea = curArea;        }    }    return maxArea;}

该解法的时间复杂度为O(n^2),运行结果显示为运行时间超时,所以需要改进算法。

3.参考解法

int maxArea(vector<int>& height){    int maxArea = 0;    int left = 0, right = height.size() - 1;    while(left < right){        maxArea = max(maxArea, min(height[left], height[right]) * (right - left));        if(height[left] < height[right])            ++left;        else            --right;    }    return maxArea;}

该解法只进行了一轮扫描,所以时间复杂度为O(n)。

4.总结
虽然参考解法看似非常简单,但这种做法需要在理论上进行证明,证明过程如下:
反证法:假如我们得到的结果不是最优的,那必定有一个比我们更好的结果,他的左右横坐标分别为aol和aor。因为我们的循环直到两根指针相遇才结束,也就是说我们必定在某个时刻有一个指针指向了aol或者aor但是没有同时指向他们。不失一般性的,假设在这个时刻,我们指向了aol,但没指向aor,此时aol有以下两种情况会发生变化。
1) aol在循环退出前没移动过。high指针一直向aol靠拢,直到他们相遇。这个时候循环退出,但是high指针在向aol靠拢时必定指向过aor,这与前提矛盾。(只要high指针经历过aor那么便会记录并得到这个假设的最优解)。
2) aol指针移动了。此时high指针在指向aor之前一定得到过比aol指的值更大的值,这个时候aol就会向右移动了。可是我们要知道,当前的aol和high指针组成的容器要比所谓的最优解(aol和aor组成的容器)更高更宽,这与aol和aor是最优解矛盾。
所有情况都矛盾,得证。

PS:

  • 题目的中文翻译是本人所作,如有偏差敬请指正。
  • 其中的“个人分析”和“个人解法”均是本人最初的想法和做法,不一定是对的,只是作为一个对照和记录。
0 0