双指针_盛水最多的容器_C++
1.题目解析
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。
在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
由图我们可以看出,一个容器的容积和两个竖板的高度还有两个板子之间的距离有关,而最多能盛的水有多高,取决于最低的那个板子有多高。
2.算法原理
2.1暴力枚举
以数据[1, 8, 6, 2, 5, 4, 8, 3, 7]
为例:
先固定最左边的数据1,依次和后面的数据结合,找出一个容积最大值。接着固定数据8,依次和后面的数据结合,找出一个容积最大值。依次类推,最后把所有取得的最大值再进行一次比较,选出最大值中的最大值。
2.2双指针+规律的解法
1.找规律:只研究小区间[6, 2, 5, 4]
从外向内枚举,如果我们先选6和4这两个板子,发现容积是12。然后固定4,从6这个较大的板子向后枚举,有两种情况:
1)里面这块板子比较小,那么宽度减小,高度也减小,容积必然是减小的。
2)里面这块板子比较大,高度不变,还是4,宽度减小,容积必然也是减小的。
由这个规律,我们就可以先算出一个容积v1
,然后大胆的舍弃板子4,继而去研究6和5的容积。
2.将规律推广,开始做题
我们可以先拿最左边的数和最右边的数,算出一个容积v1
;然后再舍去较小的板子1,去研究8和7组成的容积,记为v2
;以此类推,计算出很多小的容积,再把这些小的容积拿出来对比,找出一个最大容积。
3.代码演示
class Solution {
public:
int maxArea(vector<int>& height)
{
int left = 0;
int right = height.size() - 1;
int ret = 0; // 记录返回值
while(left < right)
{
int v = min(height[left], height[right]) * (right - left);
ret = max(ret, v);
// 移动指针
if(height[left] < height[right]) left++;
else right--;
}
return ret;
}
};