我的思路与困惑:
在本题中,我的思路大致如下,我希望能够找到一个限制条件,将指向左右两边的pointer移向中间,我是想要找到两个pointer所指的柱子所在高度中较短的一根向中间移动,然后去比较移动前后的面积较大的那一个数,但是用这个方式遇到的问题就是,如果移动后面积减少,那么我还需要移动么?如果需要,那么什么时候才终止呢,究其原因是我只是得到了思路上的一个步骤,所以并不知道为什么要这么做。
本题的思路与解法:
- 在本题中,最直观的方式其实应该是将所有可能的组合都枚举一遍,然后找到面积最大的解,那么就有n2个可能的解,算法复杂度为O(n2)
- 第二种思路大致是这样的:
- 如果当前左边柱子是1,右边柱子是7,那么大致有以下几种情况:
- 假如我们移动右边的柱子7,那么因为高度受制于最短的柱子,那么不管我们向左移动多少,高度固定为1,而宽度不断减小(即两个柱子靠得越来越近),最终的面积一定会比初始的状态小
- 假如我们移动左边的柱子1,那么高度决定于未来的左柱与固定的右柱,即min(left, 7),面积可能增大也可能减小
- 因此,我们总结以上的情况,可以发现,想要找到最大面积,就应该固定较高的柱子,移动较小的柱子,并用一个变量记录下过程中遇到的最大面积,直到遍历完所有解
- 如果当前左边柱子是1,右边柱子是7,那么大致有以下几种情况:
但是以上说法其实并不能解决我们的疑惑,或者最本质的问题,为什么这样是可行的呢?移柱子的过程,本质上来说是在不断减小搜索空间。
假如有序列1 8 6 2 5,那么它的解空间可以绘制如下:
结合本题目的条件,它的可能解为上图中橙色部分,此时我们经过分析发现固定左边柱子1,移动右边柱子的方式只会使得面积越来越小,因此我们排除所有与左边柱子1的组合(即1对应的那一整列),得到解空间如下:
经过不断的判断化简,直到所有的可能解都被我们遍历一遍(但是一定要记录最大值)
当两边柱子高度相等时,让面积变大的可能条件为这两个柱子之间存在更高的柱子,因此此时只需要随机以一个顺序移动一遍的柱子即可
我的想法:
这样的模式也许可以用于很多两个组合的情况
代码:
class Solution {
public:
int maxArea(vector<int>& height) {
int left = 0, right = height.size()-1, result = 0;
while(left < right){
int h = min(height[left], height[right]);
result = max(h * (right-left), result);
if(height[left] < height[right]){
left++;
}else{
right--;
}
}
return result;
}
};