[路飞]_leetcode刷题_11. 盛最多水的容器

94 阅读2分钟

题目

11. 盛最多水的容器

给你 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

示例 3:

输入:height = [4,3,2,1,4]
输出:16

示例 4:

输入:height = [1,2,1]
输出:2

解法

思路

暴力的循环遍历,稍微优化逻辑,省去一些不需要的计算。 具体见代码。

代码如下

/**
 * @param {number[]} height
 * @return {number}
 */
var maxArea = function(height) {
    let len = height.length;
    let S = 0;
    // 遍历数组,用每一项去和剩下的高度做乘法,取最大的面积,中间有判断优化
    for(let i=0;i<len;i++){
        let maxHeight = height[len-1];
        // 左边柱从左往右遍历,右边柱则从右往左遍历
        for(let j=len-1;j>=i;j--){
            let width = j-i;
            // 如果右边柱的高度大于左边柱,那么右边柱就不用再往前找了,往前再找面积也不会大,面积当前项*宽度
            if(height[j]>height[i]){
                S = Math.max(S,height[i]*width);
                break;
            }else{
                // 如果右边柱小于左边柱,且小于最大面积高度,初始最大面积高度为右边柱高度
                // 那么后面的逻辑不用走了,跳过本次循环
                if(height[j]<maxHeight){
                    continue
                }
                // 如果右边柱小于左边柱,但高度大于最大面积高度,那么计算以下这根柱子与当前左边距的面积,看看比目前的最大面积是不是会大一些
                let newS = Math.max(S,height[j]*width);
                if(newS>S){
                    maxHeight = height[j]
                    S = newS
                }
            }
        }
    }
    return S;
};

解法二

思路

在上一解法的基础上,进一步优化,使用双指针法,可以进一步省去无效计算。

该方法的核心思想

左右指针对应的高度,相比较,如leftHeight<rightHeight

那么我们就将left向右移动一格,因为对于left来说,目前的面积瓶颈是left自己,left再去根右边right左边的柱子比较,都没有任何意义,面积不可能大于leftHeight*(right-left),所以left直接右移。

同理接下来如果rightHeight<如leftHeight,那么就right左移

代码如下

/**
 * @param {number[]} height
 * @return {number}
 */
var maxArea = function(height) {
        let left = 0, right = height.length - 1;
        let S = 0;
        while (left < right) {
            let newS = Math.min(height[left], height[right]) * (right - left);
            S = Math.max(S, newS);
            if (height[left] <= height[right]) {
                ++left;
            }
            else {
                --right;
            }
        }
        return S;
};