本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
解题思路
我们来分析一下这道题,我们已知:
- 水总面积 = 宽度 * 较矮柱子高度
- 两个柱子从两边往中间,宽度一定减小
- 如果移动高柱子,上面公式中(较矮柱子高度)只会减小,所以移动高柱子没有意义
- 如果移动矮柱子,上面公司里(较矮柱子高度)可能会变高,此时新算的总面积就有可能比原来的更大
- 这个时候在去比较面积,如果面积更大,就更新面积最大值。
思路一
我们先定义两个指针,一个从数组的起始位置开始,另外一个从数组的最后一个元素开始,在进行比较两个指针所在的元素的大小,如果左指针对应的值的小于右侧,则左指针往右挪一位,并取得当前挪动之后的值为高,否则,右指针往左挪一位,并取得当前挪动之后的值为高, 然后在和两指针之前的差值+1求面积,最后依次求面积,返回所有的面积中最大值就是最大容水器
function maxArea(height){
let start = 0
let end = height.length-1
let maxContainer = 0
while(start<end){
let minheight = height[start] < height[end] ? height[start++] : height[end--]
let area = minheight * (end-start+1)
maxContainer = Math.max(maxContainer,area)
}
return maxContainer
};
思路二
我们也可以使用双for循环进行暴力解开,通过遍历所有可能组成容器的两边,求得所盛水的量,在其中取最大值
var maxArea = function (height) {
if (height.length < 2) return 0;
let max = 0;
for (let j = 0; j < height.length - 1; j++) {
for (let i = j + 1; i < height.length; i++) {
let l = height[j];
let r = height[i];
let sum = Math.min(l,r) * (i - j)
max = Math.max(sum,max);
}
}
return max;
};