牛客 NC128—接雨水问题

https://www.nowcoder.com/questionTerminal/31c1aed01b394f0b8b7734de0324e00f

给定一个整形数组arr,已知其中所有的值都是非负的,将这个数组看作一个柱子高度图,计算按此排列的柱子,下雨之后能接多少雨水。

 

 

备注: 1\leqslant N\leqslant 10^{6}

题解一:

双指针left,right分别从两边向中间遍历,找到每个水洼的边界。

在每一次循环中,从左向右遍历,当右边的高度小于当前左边界的高度时,这个位置上可以接水,累加接水量。当右边的高度大于当前左边界的高度时,更新左边界高度,将左指针left更新为当前位置。

从右向左遍历时,相同方法更新右边界高度,并在左边高度大于右边界高度时将右指针right位置不断向左更新。

当left和right位置重合或相邻时循环停止。

class Solution {
public:
    /**
     * max water
     * @param arr int整型vector the array
     * @return long长整型
     */
    long long maxWater(vector<int>& arr) {
        // write code here
        int lh, rh, len, left, right;
        long long water=0, lsum=0, rsum=0;
        len = arr.size();
        lh = arr[0];
        rh = arr[len - 1];
        left = 0;
        right = len-1;
        while(right - left > 1){
            for(int i = left+1 ; i <= right ; i++){
                while(arr[i] == lh && i - left == 1){
                    lsum = 0;
                    left = i;
                    lh = arr[i];
                    i++;
                }
                if(arr[i] < lh) lsum += arr[i];
                else{
                    if(i - left > 1) water += 1LL * (i - left - 1) * lh - lsum;
                    lsum = 0;
                    left = i;
                    lh = arr[i];
                    break;
                }
            }
            for(int i = right-1 ; i >= left ; i--){
                while(arr[i] == rh && right - i == 1){
                    rsum = 0;
                    right = i;
                    rh = arr[i];
                    i--;
                }
                if(arr[i] < rh) rsum += arr[i];
                else{
                    if(right - i > 1) water += 1LL * (right - i - 1) * rh - rsum;
                    rsum = 0;
                    right = i;
                    rh = arr[i];
                    break;
                }
            }
        }
        return water;
    }
};

题解二:单调栈

单调栈介绍:https://www.zhihu.com/tardis/sogou/art/26465701

用单调栈从前到后维护每一个柱子,当一个柱子出栈时累加图中每一个矩形的面积。

 k为当前栈顶的位置,i为当前准备入栈的位置,当第j根柱子被弹出栈时,计算矩形面积为(i-k-1) * ( min(arr[i],arr[k]) - arr[j] )

class Solution {
public:
    /**
     * max water
     * @param arr int整型vector the array
     * @return long长整型
     */
    
    long long waterFromLeft(vector<int>& arr){
        stack<int> s;
        int j,k;
        long long water = 0;
        for(int i = 0 ; i < arr.size() ; i++){
            while( !s.empty()){
                if(arr[i] >= arr[s.top()]){
                    j = s.top();
                    s.pop();
                    if( !s.empty()){
                        k = s.top();
                        water += 1LL * (i-k-1) * ( min(arr[i],arr[k]) - arr[j] );
                    }
                }
                else break;
            }
            s.push(i);
        }
        return water;
    }
    
    
    long long maxWater(vector<int>& arr) {
        // write code here
        long long water = 0;
        water = waterFromLeft(arr);
        return water;
    }
};

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值