给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
题解:
这题刚拿到手的时候也是一脸懵逼,瞟了一下题解
看到双指针的时候稍微有一点底。
/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function(height) {
var left = 0;//初始化左边的指针 指向数组的第一个
var right = height.length-1;//初始化右边的指针 指向数组的最后一个
var area = 0;//初始化面积为零
//当两个指针相遇 整个过程结束
while(left != right){
//h为水的高度,数值小的就是当前的高度
var h = height[left]<height[right]?height[left]:height[right];
//运算当前的面积,并与之前的面积进行比较,最后取大的那个
area = h*(right-left)>area?h*(right-left):area;
//移动指针
if(height[left]>height[right]){
right = right - 1;
}else{
left = left + 1;
}
}
return area;
};
这题的主要难点我认为有两个,一个是跳出循环的条件(可能是我蠢,我想了好久),还有一个是每次判断完area以后要怎么变换指针。
任何的算法题都不是一步到位的,我们拿到算法的第一步就是想到什么就写什么。比如我最开始就声明两个指针,并把它们初始化。然后我声明了一个h变量,这个用来记录当前的水高度,并且用双目运算符写了表达式。接着写area的表达式。
到这里我所有第一时间能想到的都写完了。
再就是该怎么控制循环结束和移动指针。
移动指针有两种情况:
- height[left]>height[right]
- height[left]<height[right]
这时候肯定是用if和else来控制
那到底怎么移动呢?
这时就是贪心法的思维了
因为我们的指针是从最两边开始的,所以在最初的情况下,我们保证了宽度最大,那么接下来只要保证高度就好了,所以每一次移动的时候要尽量保留数值大的那个。
于是就有了:
if(height[left]>height[right]){
right = right - 1;
}else{
left = left + 1;
}
}
那么写到这里差不多就能知道循环条件了,整个过程在不停变换的就是我们的两个指针,所以循环跳出的条件就是!他们相遇了!
—完结撒花—