[LeetCode]Container With Most Water

来源:互联网 发布:七了个三淘宝 编辑:程序博客网 时间:2024/06/16 16:11

题目要求:

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 linei 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.

Note: You may not slant the container.

这个题目的意思大概是这样:给出n个非负数a1到an,在坐标上有n条竖直的线,这些线的两端的坐标就为(i,0)和(i, ai)。从n条线中

找出两条线,这两条线与X轴形成的开口容器的容量(即面积)最大。举个例子,如下图所示,那么给出的a1到an就应该为:

3,2,2,10,1,9,4。而找出的2条线应该为ai = 10 和 aj = 9 这2条,最大的面积为 9 * 2 = 18(因为是盛水用的,所以以最短的板为高)。

 

  
所求的是面积,所以可以从面积的公式入手。面积(s) =高(h)*宽(w),那么我们可以先固定宽度,这样比较高的时候就能
 
直接知道是不是最大值的潜在目标了。需要注意的是,因为是装水容器,因此2条线中高较小的那个决定了h的值。
 
所以对有n个非负数的数组height,设置2个指针i和j,用于标记当前最高的左线和右线。
 
i初始指向数组开始,即i = 0,而j指向数组末,即 j = height.size() -1。再设2个指针p和q用于移动。
 
开始时,p=i, q=j, 此时宽 w = q - p = j - i是最大的,而当前最大值max = min(height[p], height[q]) * (q - p) =min(height[i], height[j]) *
 
(j - i) 。要想超越这个最大值max,则需要有一个更高的线比min(height[p], height[q])的值大,虽然此时宽比初始的时候要小,但相乘
 
起来比max大的可能性也是有的。
 
现在我们假设height[p]是比较小的那一个,这时需要找一个比height[p]高的线才有可能使乘积超越max值。所以p从当前最高左线i位
 
置出发,如果height[p]不比height[i]大,说明height[p] * (q - p)不可能超越max,因为q > i, q - p 必小于j - i 。因此直接忽略这个位
 
置,直到找到一个height[p]大于height[i],这时乘积为temp = min(height[p], height[q]) * (q - p),
 
分为以下2种情况:
 
1. 如果temp < max,不用修改max值;
 
2. 如果temp > max,修改max值。
 
无论是情况1还是情况2,都要修改i值,i = p,因为i标记着当前最高左线。这时指针p停止了继续向后,因为找到了一个比原来i标记
 
位置更高的线。进入下一轮指针游走,因为更新了线高,所以这个时候是p向后还是q向前,就需要看当前height[p]和height[q]哪个最
 
小,p位置的高度小,则p向后找更高的线,q位置的高度小,则q向前找更高的线。这个过程一直循环,直到p = q为止,此时宽为
 
0。
 
以上图为例,开始时,i = 0, j = 5, p = i, q = j, max  = min(height[i], height[j]) * (j - i)  = 3 * 5 = 15。
 
因为height[p] = 3 小于 height[q] = 4,因此p向后找,直到p = 2时,height[p] = 10,才找到了比i位置高的线。这个时候
 
temp = min(height[p], height[q]) * (q - p) = 4 * 3 = 12,比max小,直接进入下一轮循环。这个时候p已经在位置2,q在
 
位置5,height[p] = 10 大于 height[q] = 4,所以轮到q向前。q向前找到位置4,height[q] = 9 大于j位置的值4,此时求
 
乘积temp = min(10,9) * 2 = 18,比max大,更新max值。更新j值为j = q,j还是为当前最高右线。
 
这时height[p] = 10 大于 height[q] = 9,q继续向前,位置3不合适,位置2为p,停止算法。最终结果为18。
 
有了以上分析,就可以写出AC的代码了。
 
我的代码如下,欢迎各位大牛指导交流~
 
AC,Runtime: 108 ms
//LeetCode_Container With Most Water//Written by zhou//2013.11.14class Solution {public:    inline int min(int a, int b)    {        return a < b ? a : b;    }        int maxArea(vector<int> &height) {        // IMPORTANT: Please reset any member data you declared, as        // the same Solution instance will be reused for each test case.        int i = 0, j = height.size() - 1;        int p = i, q = j;        int max = min(height[i],height[j]) * (j - i);        int temp = 0;        while(p < q)        {               if (height[p] <= height[q])            {                while(++p < q && height[p] <= height[i])                 {                    //do nothing                }                if (p < q)                {                    temp = min(height[p],height[q]) * (q - p);                    if (temp > max)                    {                        max = temp;                    }                    i = p;                }            }            else            {                while(--q > p && height[q] <= height[j])                 {                    //do nothing                }                if (p < q)                {                    temp = min(height[p],height[q]) * (q - p);                    if (temp > max)                    {                        max = temp;                    }                    j = q;                }            }        }        return max;    }    };

原创粉丝点击