42. Trapping Rain Water

来源:互联网 发布:淘宝买家怎么修改评论 编辑:程序博客网 时间:2024/06/06 09:11

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,0,2数字组合能存1个单位的水(1-0),2,1,2,1,3能存(2-1)+(2-0)+(2-1)=4个单位的水,下面的搜索应该从3开始,但是后面没有比3大的数字,因此略过3,从2开始,2,1,2能存(2-1)=1,所以一共是6个单位的水。但是这样的方法有问题,比如遇到3的时候,只能遍历完后面的数字才能知道没有比它大的数字,这就导致了一些无用的计算,我看到网上有方法是先找到整个数组中的最大值,然后分别计算最大值左边和最大值右边的存水量。

这里采用的方法是从左右两边向中间进行搜索,直到两边的指针重合,搜索完成。这时候需要先初始化left和right的值,如果left<=right,说明从左往右搜索肯定能找到结束的点,那么就记录能够存的水的量,当left>right时,就从右往左搜索,最后返回res的值即可。代码如下:

int len = height.length;    if(len<3){return 0;}    int l = 0;    int r = len-1;    int res=0;    while(l<r){    int left = height[l];    int right = height[r];    if(left<=right){    while(l<r&&left>=height[++l]){    res += left-height[l];    }    }    else{    while(l<r&&right>=height[--r]){    res += right-height[r];    }    }    }    return res;
先写到这儿吧,本来想写一下找最大值然后分别找最大值左右两边的存水量的,但是电脑太卡了==高考的日子,祝各位金榜题名,如果高考的同学们报计算机专业的话,高考只意味着以后你们在哪儿写代码==