题目要求:
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.14
class 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;
}
};