盛最多水的容器

GitHub跳转原题关系图返回列表

双指针维护区间,面积由短板决定,每次移动较矮一侧,O(n)。

OJ: leetcodecn

题目 ID: container-with-most-water

难度:普及+/提高

标签:双指针贪心数组cpppython

日期: 2026-07-28 22:03

题意

给定 n 条垂线的高度,找出两条线,使它们与 x 轴构成的容器能容纳最多的水。

思路

暴力枚举所有 (i,j) 对 O(n²)。优化:左右指针从两端向中间移动,每次移动较矮的一侧。

正确性证明:设当前左右指针为 l、r,面积 = (r-l) × min(h[l], h[r])。如果移动较高的一侧,新面积的高度不会超过 min(h[l], h[r]),而宽度变小,面积一定不会更大。所以只能移动较矮的一侧,才有可能获得更大的面积。

代码

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 */
// main.cpp:双指针,每次移动较矮一侧,O(n)。
#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    int maxArea(vector<int> &height) {
        int l = 0, r = height.size() - 1, ans = 0;
        while (l < r) {
            int h = min(height[l], height[r]);
            ans = max(ans, (r - l) * h);
            if (height[l] < height[r])
                l++;
            else
                r--;
        }
        return ans;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<int> h(n);
    for (int &x : h)
        cin >> x;
    cout << Solution().maxArea(h) << '\n';
    return 0;
}
python
#!/usr/bin/env python3
from typing import List


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


def main() -> None:
    n = int(input())
    height = list(map(int, input().split()))
    print(Solution().maxArea(height))


if __name__ == "__main__":
    main()

复杂度

  • 时间复杂度:O(n),指针各移动一次。
  • 空间复杂度:O(1)。

总结

"短板决定、移动短板"是双指针求区间最值问题的经典模型。关键在于证明移动长板不可能得到更优解。