盛最多水的容器

person 不秃顶程序猿    watch_later 2024-08-06 21:20:25
visibility 280    class 贪心,数组,双指针    bookmark 专栏

给定一个长度为 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.length

  • 2 <= n <= 105

  • 0 <= height[i] <= 104

解法一:

/**
 * @param {number[]} height
 * @return {number}
 */
var maxArea = function(height) {
    if (!height || height.length < 2) {
        return 0;
    }
    let max = 0;
    let res = 0;
    for (let i = 0; i < (height.length - 1); i++) {
        for (let j = i + 1; j < height.length; j++) {
            if (height[i] < height[j]) {
                res = height[i] * (j - i);
            } else {
                res = height[j] * (j - i);
            }
            if (res > max) {
                max = res;
            }
        }
    }
    return max;
};

耗时久,性能差


这个问题是著名的“盛水最多的容器”问题,可以通过双指针法来高效地解决。该算法的关键在于逐步缩小范围,同时记录能够容纳的最大水量。

解决方案概述

给定一个整数数组 height,我们需要找到两个索引 i 和 j(其中 i < j),使得 min(height[i], height[j]) * (j - i) 的值最大。这就是容器的最大水容量。

算法步骤

  1. 初始化双指针

    • 设置两个指针,左指针 left 初始化为数组的起始位置 0,右指针 right 初始化为数组的终止位置 n-1,其中 n 是数组的长度。

  2. 计算当前水容量

    • 在每一步中,计算由 left 和 right 指针所确定的容器的水容量:min(height[left], height[right]) * (right - left)

    • 如果这个容量比目前记录的最大容量要大,就更新最大容量。

  3. 移动指针

    • 由于水容量受限于短板(较短的那一边),我们选择移动高度较小的一端指针(即 height[left] 和 height[right] 中较小的那一个)来尝试寻找更长的高度。

    • 如果 height[left] < height[right],就把 left 指针右移(left++),否则就把 right 指针左移(right--)。

  4. 重复步骤2和步骤3,直到两个指针相遇。

  5. 输出结果

    • 当两个指针相遇时,已经找到了最大水容量,输出这个最大值。

代码实现

def maxArea(height):
    # 初始化双指针
    left, right = 0, len(height) - 1
    max_water = 0
  
    while left < right:        # 计算当前容器的水容量
        current_water = min(height[left], height[right]) * (right - left)      
        # 更新最大水容量
        max_water = max(max_water, current_water)      
        # 移动指针
        if height[left] < height[right]:
            left += 1
        else:
            right -= 1
  
    return max_water# 示例测试heights = [1,8,6,2,5,4,8,3,7]print(maxArea(heights))  # 输出: 49

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组的长度。每个元素最多被访问一次。

  • 空间复杂度:O(1),只使用了常量级别的额外空间。

示例

对于 heights = [1,8,6,2,5,4,8,3,7],上述代码将输出 49。这对应于垂线索引 1 和 8,它们之间的距离是 7,较短的垂线高度是 7,因此水容量是 7 * 7 = 49

这个算法通过聪明地选择指针移动来高效地找到最优解,并且避免了冗余计算。


评论区
评论列表
menu