一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 4 天,点击查看活动详情。
盛最多水的容器
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
输入:height = [1,1]
输出:1
提示:
n == height.length2 <= n <=0 <= height[i] <=
思路分析
方法一
- 不管何时,遇到这样的题目我的第一反应,还是要将所有的情况遍历出来,然后取最大值;
- 因为做二次遍历数组,将所有情况的面积存储在 res 中,最后给 res 排序,取最大值;
- 第一次执行,得出的结论是 解答错误,错误提示是
JavaScript heap out of memory,需要存入 res 中的数据太多,所以会出现这种情况; - 于是改了存储在 res 中的数据,取每一项的最大面积存储,循环中的代码改为如下后最终的执行结果为超出时间限制,看来这种方法行不通了。
let temp = 0
for(let j = i + 1; j < len; j++) {
temp = Math.max(temp, Math.abs(j - i) * Math.min(height[i], height[j]))
}
res.push(temp)
方法二
- 以
i、j表示容器的两端,看待储水量可以得出如下结论:- 若
height[i] > height[j],那么i往右移动后,与j形成的容器的最大储水量可能减小或不变; - 若
height[i] < height[j],那么i往右移动后,与j形成的容器的最大储水量可能增大或不变
- 若
- 那么,循环数组,逐渐进行
i++和j--得到最大储水量即可。
AC 代码
方法一
/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function(height) {
const res = []
const len = height.length
for(let i = 0; i < len; i++) {
for(let j = i + 1; j < len; j++) {
res.push(Math.abs(j - i) * Math.min(height[i], height[j]))
}
}
res.sort((a,b) => b - a)
return res[0]
};
结果:
- 执行结果: 解答错误
方法二
/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function(height) {
if(height.length <= 1) return 0
let i = 0
let j = height.length-1
let res = 0
while(i < j) {
if(height[i] < height[j]) {
res = Math.max(res, height[i] * (j - i))
i++
} else {
res = Math.max(res, height[j] * (j - i))
j--
}
}
return res
};
结果:
- 执行结果: 通过
- 执行用时:76 ms, 在所有 JavaScript 提交中击败了58.91%的用户
- 内存消耗:48.5 MB, 在所有 JavaScript 提交中击败了15.89%的用户
- 通过测试用例:60 / 60