【力扣Hot100】11. 盛最多水的容器

1、题目链接

11. 盛最多水的容器

2、题目描述

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

3、核心思路

1、暴力破解

  • 两层for循环遍历,记录所有的面积,留下最大的面积

2、双指针

思路
使用双指针从数组的两端开始向中间移动。每次移动较矮的指针,计算当前面积并更新最大值。这样可以确保在移动过程中不会错过可能的更大面积。

步骤

  1. 初始化左指针 left = 0 和右指针 right = len(height) - 1,以及最大面积 max_area = 0
  2. left < right 时循环:
    • 计算当前容器的面积:current_area = (right - left) * min(height[left], height[right])
    • 更新 max_area
    • 移动较矮的指针(若左指针较矮则右移,否则左移)。
  3. 返回 max_area

正确性证明
每次移动较矮的指针,可以确保不会错过更大的面积。因为容器的容量受限于较矮的一边,移动较高的指针无法增加容量,而移动较矮的指针可能找到更高的边界。


代码实现

Java
class Solution {
    public int maxArea(int[] height) {
        int maxArea = 0;
        int left = 0;
        int right = height.length - 1;
        while (left < right) {
            int currentHeight = Math.min(height[left], height[right]);
            int currentArea = currentHeight * (right - left);
            maxArea = Math.max(maxArea, currentArea);
            if (height[left] < height[right]) {
                left++;
            } else {
                right--;
            }
        }
        return maxArea;
    }
}
C++
class Solution {
public:
    int maxArea(vector<int>& height) {
        int max_area = 0;
        int left = 0, right = height.size() - 1;
        while (left < right) {
            int current_height = min(height[left], height[right]);
            max_area = max(max_area, current_height * (right - left));
            if (height[left] < height[right]) {
                left++;
            } else {
                right--;
            }
        }
        return max_area;
    }
};
Go
func maxArea(height []int) int {
    maxArea := 0
    left, right := 0, len(height)-1
    for left < right {
        currentHeight := min(height[left], height[right])
        currentArea := currentHeight * (right - left)
        if currentArea > maxArea {
            maxArea = currentArea
        }
        if height[left] < height[right] {
            left++
        } else {
            right--
        }
    }
    return maxArea
}

func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}
Python
class Solution:
    def maxArea(self, height: List[int]) -> int:
        max_area = 0
        left, right = 0, len(height) - 1
        while left < right:
            current_height = min(height[left], height[right])
            current_area = current_height * (right - left)
            max_area = max(max_area, current_area)
            if height[left] < height[right]:
                left += 1
            else:
                right -= 1
        return max_area
JavaScript
var maxArea = function(height) {
    let maxArea = 0;
    let left = 0, right = height.length - 1;
    while (left < right) {
        const currentHeight = Math.min(height[left], height[right]);
        const currentArea = currentHeight * (right - left);
        maxArea = Math.max(maxArea, currentArea);
        if (height[left] < height[right]) {
            left++;
        } else {
            right--;
        }
    }
    return maxArea;
};

复杂度分析

  • 时间复杂度:O(n),仅需一次遍历数组。
  • 空间复杂度:O(1),仅使用常数空间。
力扣上的“最多容器”是一道经典的算法题,主要考察双指针技巧的应用。题目描述大致为:给定一个长度为 n 的非负整数数组 height,其中每个元素表示一条垂直线的高度。找出两条线,使得它们与 x 轴共同构成的容器可以容纳最多。 ### 解法思路 我们可以采用 **双指针** 方法来高效解决问题: 1. 初始化两个指针 `left` 和 `right` 分别指向数组的第一个位置和最后一个位置。 2. 计算当前两个指针所围成的面积 `(right - left) * min(height[left], height[right])` 并更新最大值。 3. 每次移动高度较小的那个指针(因为如果移动较大的那个指针,则无论如何都不会让量增加),直到两指针相遇为止。 4. 最终得到的最大面积即为答案。 这种方法的时间复杂度为 O(n),比暴力解法更优。 --- #### 示例代码 (Python) ```python def maxArea(height): left, right = 0, len(height) - 1 max_area = 0 while left < right: # 当前面积计算 current_area = (right - left) * min(height[left], height[right]) max_area = max(max_area, current_area) # 移动较短的一侧指针 if height[left] < height[right]: left += 1 else: right -= 1 return max_area ``` --- ### 关键点解析 1. 双指针从两端开始逼近的原因在于我们试图寻找更大的宽度组合,并动态调整高度限制条件。 2. 如果只移动较高的那一端,由于宽度减少而无法提升高度,因此不会带来更好的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值