Leetcode: 盛最多水的容器

28 阅读2分钟

原题:leetcode.cn/problems/co…

题目描述

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

**说明:**你不能倾斜容器。

解题思路

  1. 双指针逼近
    • 初始化左右指针分别指向数组首尾
    • 计算当前容量:min(height[left], height[right]) * (right-left)
    • 更新最大容量记录
  2. 指针移动策略
    • 移动高度较小的指针(短板效应)
    • 较小高度决定容量上限
  3. 收敛扫描
    • 指针向中心收敛直至相遇
    • 每次移动都尝试提升短板高度
  4. 数学原理
    • 宽度递减时,只有增大高度才能提升容量
    • 较高端固定时移动低端更优

关键洞察

  1. 短板效应
    • 容器容量由较短边决定
    • 移动长边无法增加容量
  2. 宽度-高度平衡
    • 初始最大宽度优先
    • 牺牲宽度换取高度提升
  3. 决策最优性证明
    • 每次移动都保证不错过最优解
    • 扫描过程覆盖所有潜在最优组合
  4. 无后效性
    • 指针移动只依赖当前状态
    • 无需回溯历史位置

复杂度分析

指标说明
时间复杂度O(n):左右指针共遍历n个元素
空间复杂度O(1):仅使用常数额外变量

代码实现

var maxArea = function (height) {
    let l = 0, r = height.length - 1;
    let maxWater = 0;

    while (l < r) {
        const hl = height[l], hr = height[r];
        // 计算当前容器水量
        const currentWater = Math.min(hl, hr) * (r - l);
        maxWater = Math.max(maxWater, currentWater);

        // 跳过无法增加面积的情况
        if (hl < hr) {
            // 移动左指针直到找到更高的柱子
            while (l < r && height[l] <= hl) l++;
        } else {
            // 移动右指针直到找到更高的柱子
            while (l < r && height[r] <= hr) r--;
        }
    }

    return maxWater;
};

相似题目