LeetCode 热题 HOT — 盛最多水的容器

335 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 4 天,点击查看活动详情

盛最多水的容器

原题地址

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

示例 1:

image.png

输入:[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.length
  • 2 <= n <=10510^5
  • 0 <= height[i] <=10410^4

思路分析

方法一

  1. 不管何时,遇到这样的题目我的第一反应,还是要将所有的情况遍历出来,然后取最大值;
  2. 因为做二次遍历数组,将所有情况的面积存储在 res 中,最后给 res 排序,取最大值;
  3. 第一次执行,得出的结论是 解答错误,错误提示是 JavaScript heap out of memory,需要存入 res 中的数据太多,所以会出现这种情况;
  4. 于是改了存储在 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)

方法二

  1. i、j 表示容器的两端,看待储水量可以得出如下结论:
    • height[i] > height[j],那么 i 往右移动后,与 j 形成的容器的最大储水量可能减小或不变;
    • height[i] < height[j],那么 i 往右移动后,与 j 形成的容器的最大储水量可能增大或不变
  2. 那么,循环数组,逐渐进行 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

END