【LeetCode热题100】No.11——盛最多水的容器

大家好!今天继续更新LeetCode热题100系列,第五题我们来学习中等题"盛最多水的容器"。这道题是双指针技巧的经典应用,核心考查如何通过贪心策略优化遍历过程。接下来,我们从题目分析、思路推导到Java代码实现,逐步掌握最优解法。

一、题目描述

首先明确题目要求(基于LeetCode官方原题):

  • 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, heighti) 。
  • 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
  • 返回容器可以储存的最大水量。
  • 说明:你不能倾斜容器。

示例

示例1: 输入: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

提示

  • n == height.length
  • 2 <= n <= 10⁵
  • 0 <= heighti <= 10⁴

二、解题思路分析

这道题的核心是计算"两条垂线与x轴构成的容器的盛水量",并找到最大值。盛水量的计算公式是:min(左垂线高度, 右垂线高度) × 两条垂线之间的距离

1. 暴力解法(时间不达标)

思路

遍历所有可能的两条垂线组合,计算每个组合的盛水量,记录最大值。

问题

时间复杂度为O(n²),当n=10⁵时,运算次数达10¹⁰,会超时,因此必须优化。

2. 最优思路:双指针法(O(n)时间)

核心逻辑

利用"贪心策略",通过左右指针向中间移动,减少无效计算:

  • 初始时,左指针在最左端(i=0),右指针在最右端(j=height.length-1),此时宽度最大。
  • 计算当前盛水量,更新最大值。
  • 移动指针:谁矮就移动谁(因为盛水量由矮的一边决定,移动高的一边只会让宽度减小,盛水量一定变小;而移动矮的一边可能遇到更高的垂线,盛水量可能增大)。
  • 重复上述步骤,直到左右指针相遇。
为什么可行?

假设左指针i的高度小于右指针j的高度,此时若移动j,新的盛水量为min(heighti, heightj-1) × (j-1-i),由于heighti是限制因素,新水量只会小于等于原水量;而移动i,可能遇到更高的heighti+1,新水量可能增大。因此"移动较矮的指针"是最优选择。

三、Java代码实现(双指针法)public class Solution {

java 复制代码
public int maxArea(int[] height) {
    int left = 0; // 左指针,初始在最左端
    int right = height.length - 1; // 右指针,初始在最右端
    int maxArea = 0; // 记录最大盛水量
    while (left < right) {
        // 计算当前左右指针构成的容器的盛水量
        int currentWidth = right - left;
        int currentHeight = Math.min(height[left], height[right]);
        int currentArea = currentWidth * currentHeight;
        // 更新最大盛水量
        maxArea = Math.max(maxArea, currentArea);
        // 移动较矮的指针(贪心策略)
        if (height[left] < height[right]) {
            left++;
        } else {
            right--;
        }
    }
    return maxArea;
}

}

代码解析

  1. 指针初始化 :左指针left从0开始,右指针right从数组末尾开始,确保初始宽度最大。
  2. 计算当前盛水量 :根据公式宽度×最小高度计算,其中宽度是right - left,高度取左右指针高度的较小值。
  3. 更新最大值 :用Math.max比较当前盛水量和历史最大值,保留较大值。
  4. 移动指针 :若左指针高度较低,则右移左指针;否则左移右指针,直到两指针相遇(left < right条件不满足)。
  5. 返回结果 :遍历结束后,maxArea即为最大盛水量。

四、测试案例验证

测试案例1:基础示例

输入:height = [1,8,6,2,5,4,8,3,7]

处理过程:

  • 初始:left=0(h=1),right=8(h=7),面积=8×1=8,max=8 → 移动left(1<7)
  • left=1(h=8),right=8(h=7),面积=7×7=49,max=49 → 移动right(7<8)
  • left=1(h=8),right=7(h=3),面积=6×3=18 <49 → 移动right
  • ...(后续步骤省略)
  • 最终max=49,正确。

测试案例2:最短示例

输入:height = [1,1]

处理:left=0,right=1,面积=1×1=1,移动任意指针后循环结束,输出1,正确。

五、复杂度分析

  • 时间复杂度:O(n)。左右指针从两端向中间移动,每个元素最多被访问一次,总操作次数为n级。
  • 空间复杂度:O(1)。仅使用常数个额外变量,无额外空间开销。

六、总结

"盛最多水的容器"的解题关键是双指针+贪心策略,核心要点如下:

  1. 盛水量由"宽度"和"最小高度"共同决定,初始时宽度最大。
  2. 移动较矮的指针是最优选择,因为这是唯一可能使盛水量增大的方式。
  3. 双指针法将时间复杂度从O(n²)降至O(n),高效解决大数据量问题。

这道题的双指针技巧具有通用性,可迁移到其他"范围查找最大值"的问题中。下一篇我们继续讲解LeetCode热题100的下一道题。

相关推荐
江畔柳前堤3 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Forever Nore4 小时前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考5 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX6 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面7 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号7 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽7 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI7 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者9 小时前
征程6工具链模型X86推理方式说明
算法
地平线开发者9 小时前
【征程6】校准量化中HistogramObserver解析
算法