[LeetCode] (medium) 11. Container With Most Water

本文探讨了LeetCode上的经典问题——容器盛水的最大面积。通过分析,提出了两种解决方案:一是使用单调栈方法,虽然直观但效率较低;二是采用双指针技术,实现了更高效的求解。最终,通过对比两种方法,强调了双指针法的优越性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://leetcode.com/problems/container-with-most-water/

Given n non-negative integers a1a2, ..., an , where each represents a point at coordinate (iai). n vertical lines are drawn such that the two endpoints of line i is at (iai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.

Note: You may not slant the container and n is at least 2.

 

The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.

 

Example:

Input: [1,8,6,2,5,4,8,3,7]
Output: 49

 这道题一开始很自然地想到的是单调栈的方法。在容器右壁确定的情况下,分析每一个容器左壁的性质有,任何一个柱右侧的不高于它的柱都不可能(作为左壁)提供更大的容积,因此维护一个壁高的单调数组(其实也不能说是栈,因为只进不出),对于每一个新来的壁如果他比当前的最高壁更高则添加到数组末尾,否则丢弃。

但是对于容器右壁,需要对原始数据中的每一个位置进行遍历并根据当时的上述单调数组中的值选择相应的最大容量左壁。考虑到容器的宽有时候能够提供比高更多的容积(如1 1 1.... 1 5 1),因此不能简单使用二分查找的方法选择“最大限度地利用右壁的高度”的位置,而需要至少从低到高遍历判断到这个位置。

class Solution {
public:
    int maxArea(vector<int>& height) {
        static int fast_io = []() { std::ios::sync_with_stdio(false); cin.tie(nullptr); return 0; }();
        vector<int> y;
        vector<int> x;
        y.push_back(0);
        x.push_back(-1);
        int result = 0;
        int flag = 0;
        for(int i = 0; i < height.size(); ++i){
            flag = 0;
            for(int j = 1; j < y.size(); ++j){
                if(y[j] > height[i]){
                    if(flag == 0) ++flag;
                    else break;
                }
                result = max(result, min(y[j], height[i])*(i-x[j]));
            }
            if(height[i] > y.back()){
                y.push_back(height[i]);
                x.push_back(i);
            }
        }
        return result;
    }
};

但是这个方法的复杂度太高,时间用到了340ms,显然是不理想的。

很明显导致复杂度的原因在于针对每一个右壁的选择对左壁需要进行遍历的关系(在最坏情况下就相当于枚举两壁的所有组合了),考虑对单调结构的维护添加一定的出操作,但是很难想明白。

看了别人的答案才发现其实可以将右壁使用和左壁同样的思路(其实回过头来看是很显然的,因为这个问题本身就具有很强的对称性),同时由于这个所谓的单调数组并没有“出”这个操作所以 但是需要做一定的修改,不把两壁分开考虑,作为整体之后就很明显了单调性在于两壁收拢时桶的宽度减小,欲使容积增大,桶高必须增加。(感觉很好理解,但说不明白)

class Solution {
public:
    int maxArea(vector<int>& height) {
        static int fast_io = []() { std::ios::sync_with_stdio(false); cin.tie(nullptr); return 0; }();
        int lo = 0;
        int hi = height.size()-1;
        int hei;
        int result = 0;
        while(lo < hi){
            hei = min(height[lo], height[hi]);
            result = max(result, hei*(hi-lo));
            while(lo < hi && height[lo] <= hei) ++lo;
            while(lo < hi && height[hi] <= hei) --hi;
        }
        return result;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值