[路飞]_LeetCode_盛最多水的容器

112 阅读2分钟

「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战

题目

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器。

示例 1:

image.png

输入:height = [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

来源:力扣(LeetCode)leetcode-cn.com/problems/co…

解题思路

容量计算公式为: S(i, j) = (j - i) * Math.min(height[i], height[j])

暴力破解

首先想到的是暴力破解,使用双循环分别求出每组垂直线内的容量,每次循环更新一次最大值。容量的大小取决于最短的垂直线的高度。暴力破解的时间复杂度比较差,力扣提交时会超时。

双指针

初始化双指针为 height 的两端,每循环一次小的一边向内缩进(因为长的缩进时容量会更小),当左边大于等于右边指针时结束循环,既可获取到最大容量。

代码实现

暴力破解

var maxArea = function(height) {
    const len = height.length
    let max = 0

    for (let i = 0; i < len; i++) {
        for (let j = i + 1; j < len; j++) {
            //容量 = (j - i) * Math.min(height[i], height[j])
            max = Math.max(max, (j - i) * Math.min(height[i], height[j]))
        }
    }

    return max
};

双指针

var maxArea = function(height) {
    let l = 0
    let r = height.length - 1
    let max = 0
    
    //从两侧开始,短的一边向内缩进
    while (l < r) {
        max = Math.max(max, (r - l) * height[height[l] < height[r] ? l++ : r--])
    }

    return max
};

如有错误欢迎指出,欢迎一起讨论!