首先这道题是可以暴力求解的,先规定一个宽度,然后遍历所有宽度为此值的情况,然后再修改宽度值,然后继续遍历。这种方法虽然可行,但是情况太多,而且效率太低,这里我们采用双指针的方法。
首先分析一段的情况,就拿图中两条红色的情况示例来说,右边垂线小于左边垂线,所以它的最大容量为宽度*右边垂线的高度,这个时候如果我们固定右边垂线,来修改左边垂线,让左边垂线往右移动,首先移动后有效容器的宽度是一定是减小的,左边垂线高度可能变大或者边小,如果垂线比之前长,容器的有效宽度减小,而有效高度是由短的一方决定的,也就是右边垂线的高度,所以有效高度是不变的;如果左边垂线移动后比右侧短,那有效高度就以短的决定,有效高度减小。所以总的来说,在固定右边垂线之后,往后移动左边垂线的结果就是,有效宽度一定减小,而有效高度减小或不变,整体有效容量一定是减小的,因此此时就没有必要再考虑左边垂线往右移动的情况。
这个时候考虑右边垂线往左移动的情况,首先有效宽度也是一定减小的,但是有效高度可能增大减小或不变,这取决于移动后的右边线高度与之前右边线和左边线的关系,他是有可能变大的,所以我们之后要讨论的就是右边线往左移动的情况。
以此类推,移动后固定短的那条边线,长的那条无论怎样移动都是没有当前有效容量大的,所以应该每次记录有效容量后,更新较短那条垂线的位置,然后再讨论更新最大值。
一开始我们从数组的左右两边开始,宽度是下标的差,高度是两者中较短的那一个,每次计算完之后向内修改较短的垂线的位置,直到左右两根边线相遇,我们保存的最大值就是题目所求的最大值了。
因为我们选择左右垂线然后逐步向内更新的操作很像我们定义了左右两个指针在移动,所以称为双指针法,实际上我们并没有真的定义两个指针,只是形式上比较像。
以下是具体代码:
class Solution {
public:
int min(int a,int b)
{
if(a>b)
{
return b;
}
else return a;
}
//返回两者中的较小值
int maxArea(vector<int>& height) {
int left = 0,right = height.size()-1;
//左右分别指向数组开头和结尾
int vmax =0;
//用来记录当前最大值,也是我们最后要返回的结果
vmax = (right-left) * min(height[left],height[right]);
//小的为有效高度,下标相减为有效宽度
//左右下标相等时候停止
while(left<right)
{
//左边大于右边就移动右边
if(height[left]>height[right])
{
right--;
vmax=max(vmax,(right-left)*min(height[left],height[right]));
}
//右边大于左边就移动左边
if(height[left]<=height[right])
{
left++;
vmax=max(vmax,(right-left)*min(height[left],height[right]));
}
}
return vmax;
}
};
以上就是这道题的解析了。
欢迎大家在评论区交流讨论,批评指正。