LeetCode 👉 HOT 100 👉 盛最多水的容器 - 中等题

544 阅读3分钟

这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战

题目

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 **(i, ai)**和 (i, 0) 。找出其中的两条线,使得它们与 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

思路

题目寻找的是两个位置 xy,它们构成的容器,可以容纳最多的水

很容易想到,暴力解法。遍历题目所给数组 height,每次取出一个,作为容器的 左边界x,再从该位置往后的数据中,每次取出一个,作为容器的 右边界y,此时容器能够储存的水量 Size = Math.min(height[x], height[y]) * (y - x),依次遍历剩下的数据作为 右边界y,每次都和上一次的储水量比较,留下较大的 Size,最后留下的 Size 即为题目所求

最终代码

    /**
     * @param {number[]} height
     * @return {number}
     */
    var maxArea = function(height) {
        let size = 0;
        for(let i = 0; i < height.length; i++) {
            for(let j = i + 1; j < height.length; j++) {
                let x = j - i;
                let y = Math.min(height[i],height[j]);
                let maxHeight = x * y;
                if(maxHeight > size) {
                    size = maxHeight;
                }
            }
        }
        return size;
    };

思考

上述的暴力解法,时间复杂度为 O(n!),当n很大的时候,算法的时间复杂度太高了,性能必然很低

这里介绍双指针的解法:

  • 新建两个指针 x, y,初始时分别指向数组的左右两端,储水量的计算公式依然为 Math.min(height[x], height[y]) * (y - x)

  • x 指针初始在数组前端,只能向数组末端移动,y 指针初始在数组末端,只能向数组前端移动

  • 关键: 每次移动 height[i] 数值较小的那个指针,重新计算储水量 (👉 为什么看官方解释 😭😭😭)

  • 每次比较保留储水量较大的数值

  • 双指针相遇时,遍历结束

代码如下

    /**
     * @param {number[]} height
     * @return {number}
     */
    var maxArea = function(height) {

        let x = 0, y = height.length - 1;

        let size = 0;

        while(x < y) {

            let area = Math.min(height[x], height[y]) * (y - x);

            size = Math.max(size, area);

            if(height[x] <= height[y]) {
                x++
            } else {
                y--
            }
        }

        return size;
    }

小结

遇到计算两个位置之间构成容积的问题,可以考虑双指针的思想,但是解法中,每次移动较小的那一个指针是不容易想到的,反而可能会去考虑各种移动情况,导致思路错乱,最后写不出解法。

解题思路 👉👉👉👉👉👉👉👉👉👉👉👉👉 解过了才有思路

解题模版 👉👉👉👉👉👉👉👉👉👉👉👉👉 解多了才有模版

LeetCode 👉 HOT 100 👉 盛最多水的容器 - 中等题

LeetCode 👉 HOT 100 👉 最长回文子串 - 中等题

LeetCode 👉 HOT 100 👉 无重复字符的最长子串 - 中等题

LeetCode 👉 HOT 100 👉 两数相加 - 中等题

LeetCode 👉 HOT 100 👉 两数之和 - 简单题