盛最多水的容器

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

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

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

说明:你不能倾斜容器。
示例 1:

输入:[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

解题思路:
双指针法,具体代码如下:
class Solution {
public:
int maxArea(vector& height) {
int left = 0;
int right = height.size() - 1;
int max_area = 0;

    while (left < right) {

        int current_height = min(height[left], height[right]);
        int current_width = right - left;
        int current_area = current_height * current_width;

        if (current_area > max_area) {
            max_area = current_area;
        }

        if (height[left] < height[right]) {
            left++;
        } else {
            right--;
        }
    }

    return max_area;
}

};

其实第一思路想到的就是双指针法,双循环暴力枚举到最后肯定超时,绝对不可取,不过难点就在于想到双指针后不敢用,因为不知道怎么证明不会漏解,下面给出一种证明双指针法不会漏解的方法。个人认为:核心思想还是贪心

证明双指针法不会漏解:

1.容器的容积公式:area = min(h[i], h[j]) × (j - i)(i < j),最大容积的关键是“较短边长度”和“间距”的平衡。
我们的目标是找到所有 (i,j) 组合中 area 最大的一对。双指针的核心操作是:初始时 i=0(最左)、j=n-1(最右),每次移动 “较短边对应的指针”,直到 i==j。
明确思路后,接下来进行关键证明:
假设短边是h[i],为什么以h[i]为边的所有解都不可能是最大值

2,对于任意 k(i < k < j),考虑组合 (i, k) 的容积
间距:k - i < j - i(因为 k < j);
较短边:min(h[i], h[k]) ≤ h[i]
要理解第二个式子,只要认识到,h[i]是当前的较短边,而我们移动的是长边所在的指针,所以长边所在指针移动后的h[k]如果有h[k]>=h[i],那么min(h[i], h[k])=h[i],如果h[k]<h[i],那么min(h[i], h[k])=h[k]<h[i],综上,min(h[i], h[k]) ≤ h[i]
接下来计算由h[k]与h[i]围成的水桶的容积:
area = min(h[i], h[k]) × (k - i)<=h[i](k-i)<h[i](j-i)=area(h[j],h[i]);

所以由上面的放缩可知,只要移动长边的指针,所得到的新的容器容积一定减小,所以,这就是双指针法的正确之处,可以判定双指针法一定不会漏解。

posted @ 2025-12-03 01:29  暗神酱  阅读(2)  评论(0)    收藏  举报