LeetCode OJ 之 Trapping Rain Water (“收集”雨水)

题目:

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.

给定n个非负整数代表一个图,每个栏的宽度为1,计算下雨后,它能盛多少水。

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!

思路:

从图中可以看出每个点 i 处的雨水量为 i 左半边高度的最大值和右半边高度的最大值中间较小的 - 当前 i 的高度,假设当前 i 处的高度小于前面两者。比如说图中的第5个的雨水量是左边的最高点即第四个(2)和右边的最高点第八个(3)中较低的 2 ,然后减去当前高度 (1)得到当前点的雨水量 1。因此只要知道当前点前半段的最高点和后半段的最高点即可。

对于每个柱子,找到其左右两边最高的柱子,所以,
1. 从左往右扫描一遍,对于每个柱子,求取左边最大值;
2. 从右往左扫描一遍,对于每个柱子,求最大右值;
3. 再扫描一遍,把每个柱子的面积并累加。
也可以,
1. 扫描一遍,找到最高的柱子,这个柱子将数组分为两半;
2. 处理左边一半;
3. 处理右边一半。

代码1:

class Solution {
public:
    int trap(vector<int>& height) 
    {
        int result = 0;
        int len = height.size();
        if(len <= 1)
            return 0;
        vector<int> f(len , 0);//保存左边的
        vector<int> g(len , 0);//保存右边的
        for(int i = 1 ; i < len ; i++)
        {
            f[i] = max(f[i-1] , height[i-1]);
            g[len-1-i] = max(g[len-i] , height[len-i]);
        }
        int tmp = 0;
        for(int i = 0 ; i < len ; i++)
        {
            tmp = min(f[i] , g[i]);
            //只有左边和右边的较小值 > 当前高度才有雨水
            if(tmp > height[i])
                result += (tmp - height[i]);
        }
        return result;
    }
};


代码2:

class Solution {
public:
    int trap(vector<int>& height) 
    {
        int result = 0;
        int len = height.size();
        if(len <= 1)
            return 0;
        int maxPos = 0;
        int max = height[0];
        //找出最高点所在位置
        for(int i = 1 ; i < len ; i++)
        {
            if(height[i] >= max)
            {
                maxPos = i;
                max = height[i];
            }
        }
        //求左半边雨水
        int leftPeak = 0;
        for(int i = 0 ; i < maxPos ; i++)
        {
            if(height[i] >= leftPeak)
                leftPeak = height[i];
            else
                result += (leftPeak - height[i]);
        }
        //求右半边雨水
        int rightPeak = 0;
        for(int j = len - 1 ; j > maxPos ; j--)
        {
            if(height[j] >= rightPeak)
                rightPeak = height[j];
            else
                result += (rightPeak - height[j]);
        }
        return result;
    }
};




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值