在问 · 算法题解

11. 盛最多水的容器

中等双指针双指针收缩力扣原题 ↗

题目描述

输入长度为 n 的整数数组 height。在平面上画 n 条竖线,第 i 条线从 (i, 0) 画到 (i, height[i])。

任选两条竖线,它们和 x 轴一起围成一个容器。容器的水面高度取决于两条线中较矮的一条,宽度等于两条线的横坐标之差,容器不能倾斜。

返回所有选法中容器能装下的最大水量,也就是宽度乘以较矮高度的最大值。

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

解释:选高度为 8(下标 1)和 7(下标 8)的两条线,宽度 7,高度 7,水量为 49。

示例 2
输入:height = [1,1]
输出:1

解释:只有两条线,宽 1、高 1,水量为 1。

数据范围

  • n == height.length
  • 2 <= n <= 10^5
  • 0 <= height[i] <= 10^4

解题思路:双指针收缩

左右指针夹住区间,面积为短板高度乘宽度。移动较短的一侧才可能获得更高短板;移动长板只会缩短宽度且短板不升高。

为什么正确

每次移动后,被排除的边不可能与当前另一边形成更优容器。

复杂度分析

时间 O(n),空间 O(1)。

易错点

不能移动较高的一侧;面积受短板限制。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def maxArea(self, height):
        l, r, best = 0, len(height)-1, 0
        while l < r:
            best = max(best, min(height[l], height[r]) * (r-l))
            if height[l] < height[r]:
                l += 1
            else:
                r -= 1
        return best

载入编辑器,自己跑一遍 →

其他解法

暴力枚举全部 O(n²) 个线对;双指针每步排除一整批不可能更优的线对,只需 O(n)。

解法 2:枚举所有线对 时间 O(n²),空间 O(1)

用两层循环枚举每一对下标 i<j,容量为 min(height[i], height[j]) * (j-i),取最大值。

直接按定义计算,一定正确,可以用来对拍验证双指针。n 达到 10^5 时会超时。双指针的关键是证明「移动较短一边不会错过最优解」,从而把 O(n²) 对线对剪枝成 O(n) 步。

class Solution:
    def maxArea(self, height):
        n, best = len(height), 0
        for i in range(n):
            for j in range(i + 1, n):
                best = max(best, min(height[i], height[j]) * (j - i))
        return best

双指针 专题的其他题目

查看 双指针 全部题目 →