75. Trapping Rain Water

本文介绍了一种计算柱状地形雨水蓄积量的高效算法。通过寻找局部最高与次高柱来划分问题,并采用左右夹逼法逐步逼近最优解。递归解决两端剩余区间,最终实现复杂度优化。
  1. Trapping Rain Water My Submissions QuestionEditorial Solution
    Total Accepted: 66869 Total Submissions: 206382 Difficulty: Hard
    Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

For example,
Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.

这里写图片描述
The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!

题意:给定一个序列,为柱子的高度,计算中间
可蓄水量

这是一个难题,这里来说说基本思路:
从上图可以看出,每段可以蓄水的区间两端的高度都是这个局部区间的最高和
次高值(或者等高),关键是找到一中可行的方式来划分相同子问题。
1.对于总区间,找到最高值和次高值包含的区间,计算中间蓄水量
2.对于除中间之外的两端区间,转化为相同子问题求解。

对于1中找最高值和次高值有很多方法,这里通过左右夹逼的方式来求,
左右比较冒泡出最优值,同时在比较过程存储了次优值

class Solution {
public:
    int trap(vector<int>& height) {
        int n= height.size();
        if(n<3)return 0;  //递归出口  
        else if(n==3){  
            if(height[1]<height[0]&&height[1]<height[2])  //三个柱子可计算容水量 
                return min(height[2]-height[1],height[0]-height[1]);
            else return 0;
        }
        else{
            int left=0,right=n-1;
            int max1=-1,max2=-1,id1,id2;
            while(left<right){   //依次从两端向中间靠拢,寻找两端的最高处 
                if(height[left]>=max1){   //保留左半部局部最高点 
                    max1 = height[left];
                    id1 = left;
                }
                if(height[right]>=max2){  //保留右半部局部最高点
                    max2 = height[right];
                    id2 = right;
                }
                if(height[left]<height[right])++left; //哪边小哪边向中间靠拢 
                else --right;
            }
            int sum=0;      
            for(int i=id1+1;i<id2;++i) //计算中间包含高度和 
                sum+=height[i];
            sum = (id2-id1-1)*min(height[id1],height[id2])-sum;//得到中间容水量 
            vector<int> fir,sec;
            auto it_beg = height.begin(),it_end=height.end();
            fir.assign(it_beg,it_beg+id1+1);
            sec.assign(it_beg+id2,it_end);
            return trap(fir)+sum+trap(sec);         //左半部容水+中间容水+右半部容水 
        }

    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值