leetcode Container With Most Water

题目

Given n non-negative integers a1, a2, …, an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) 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.
题目来源:https://leetcode.com/problems/container-with-most-water/

分析

若干根直线,求两根直线之间组成容器的最大容量。
首先,容器的高度取决于这两根线中较小的一根。与中间的线的高矮无关。
例如:1,2,1,3。当取2和3时,容量最大。
这道题和Largest Rectangle in Histogram是不一样的。

解法:

取left指针和right指针,从两头开始,往中间靠拢。如果靠拢的过程中发现height变小了就完全没必要算了,因为靠拢过程过程中宽度变小,如果高度再变小容量肯定变小。用两重循环直接暴力算也可以,复杂度是O(n^2)。

优化:

为了加快,可以先遍历一遍,暂存每个height右边第一个比它大的元素的下标,暂存每个height左边第一个比它大的元素的下标。这样双重循环是速度就能快一点。

代码

class Solution {
public:
    int maxArea(vector<int>& height) {
        int n = height.size();
        int *help_left = new int[n];
        int *help_right = new int[n];
        help_left[0] = -1;
        help_right[n-1] = n;
        for(int i = 1; i < n; i++){
            int j = i-1;
            while(height[i] > height[j] && j != -1)  j = help_left[j];
            help_left[i] = j;
        }
        for(int i = n-2; i >= 0; i--){//这个也循环可以和上面的循环糅合成一个,一次遍历就可以了。
            int j = i + 1;
            while(height[i] > height[j] && j != n) j = help_right[j];
            help_right[i] = j;
        }
        int max_area = 0;
        for(int left = 0; left < n; ){
            for(int right = n-1; right > left; ){
                int h = min(height[left],height[right]);
                int area = h * (right - left);
                if(area > max_area)
                    max_area = area;
                if(help_left[right] > left)
                    right = help_left[right];
                else
                    break;
            }
            if(help_right[left] < n)
                left = help_right[left];
            else
                break;
        }
        return max_area;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值