题目链接:盛最多水的容器
拿到这个题目,结合示意图看了下,基本上就是一个给定一组宽,高,求最大面积的题目, 同时很容易让人想到“木桶原理”,即,最短的那块板决定木桶的容量。
题目给出了一个数组,里面存放所有的高度值,宽度值可以通过计算数组索引的差得到,因此任意两个值之间面积值为:
const index1,index2;// 数组索引,index2 大于 index1
const int height1 = heightArray[index1];
const int height2 = heightArray[index2];
const int height = height1 > height2 ? height2 : height1;
const int width = index2 - index1;
const int area = width * height;
面积的计算方式有了,接下来就是遍历所有的情况计算最大值,常规的遍历方式如下:
为了后面描述方便假设索引所对应的值为v0,v1,v2,v3,v4,v5,v6
区间面积表示为area[index1, index2]
横轴代表数组索引,纵轴代表索引所对应的值,从索引0开始,分别计算[0,1],[0,2],[0,3],[0,4],[0,5],[0,6]这六个区间的面积,找到最大的面积,然后再从索引1开始,计算[1,2],[1,3],[1,4],[1,5],[1,6],以此类推计算所有情况的值,找到最大的那一个。
常规的遍历方式需要计算每种情况的值,实际上可以通过一些规律避免每种情况都去计算。
比如从索引0开始,计算面积的时候,先计算[0,6],再计算[0,5],[0,4],[0,3],[0,2],[0,1],以这种顺序计算。这样当索引递减时,宽度值也在递减,因此,计算完[0,6]再去计算[0,5]的时候,如果v5 <= v6,则area[0,5]必然小于area[0,6],通过这样的判断就可以不去计算[0,5]这个区间。后面继续按照这种方式处理[0,4],[0,3],[0,2],[0,1]。
结合上面示例图的情况就是:
[0,6] 需要计算
[0,5] 需要计算 (由于v5 > v6,记录最大值 maxHeight = v5)
[0,4] 不计算 (由于v4 < maxHeight )
[0,3] 需要计算(由于v3 > maxHeight,记录最大值maxHeight = v3)
[0,2] 不计算 (由于v2 < maxHeight)
[0,1] 不计算 (由于v1 < maxHeight)
下面是C++版的具体实现算法:
class Solution {
public:
int maxArea(vector<int>& height) {
int maxValue = 0;
const int vecLength = height.size();
int leftMaxValue = 0;
for(int i = 0; i < vecLength; i++)
{
const int leftValue = height[i];
if(leftValue > leftMaxValue)
{
leftMaxValue = leftValue;
int rightMaxHeight = 0;
int lastIndex = vecLength - 1;
while(lastIndex > i)
{
int rightValue = height[lastIndex];
if(rightValue > rightMaxHeight)
{
rightMaxHeight = rightValue;
const int width = lastIndex - i;
const int minHeight = rightValue > leftValue ? leftValue : rightValue;
const int value = minHeight * width;
if(value > maxValue)
{
maxValue = value;
}
}
lastIndex--;
}
}
}
return maxValue;
}
};