42. 接雨水

原始题目

给定n个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
示例:

输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

分析

看到这个就会想到木桶效应,即所盛的水由短板决定。这里也是同理。

example

以上图为例分析一下过程,从左至右开始,位置1肯定是边界,也就是说位置1右边部分的水位绝对不可能高于此,所以我们可以从此开始遍历,如果后一位置的高度低于位置1,则假设这里的水位可以与1齐平,然后往后到位置6,一看,这里的高度高于位置1,也就是说,不管你6往后的洪水滔天,和位置1到5的水位无关,前面已经固定了。那么继续往后,由于不用考虑前面的,那么位置6相当于变为了位置1。但是到了位置8,此时最高为此位置,一直往后,到了位置12,由于位置12高度小于位置8,也就是说之前的假设的水位不可能真的达到,需要减去部分水位,那需要怎么减?这里处理就会麻烦,那么为什么1到6不用考虑减去呢?因为6高于1,假如12的位置也高于8,那么也不用考虑减去。所以根据短板效应,我们应该用短的那块高度做假设水位,即从高度低的向高度高的去移动。
但是如果从左至右依次遍历,除特殊情况,否则不可能始终从高度低的向高度高的走,所以不能从一端遍历,需要从两端同时遍历。

伪代码如下:

while(左端最高的位置在右端最高位置之前){
    if(左端最高的高度<右端最高的高度){
        左端位置向右移动,如果此位置小于最高则并记录下水位增加,否则此位置变为最高
    }
   else{
       右端位置向左移动,如果此位置小于最高则记录下水位增加,否则次位置变为最高
    }
}

Leetcode C++代码实现如下:

class Solution {
public:
    int trap(vector& height) {
        int len = height.size();
        if(len==0) return 0;
        int ret=0;
        int lindex = 0, rindex = len-1;
        int left = height[lindex], right = height[rindex];
        while(lindex

由于只遍历了一次,且存储空间和长度无关,则时间复杂度为O(n),空间复杂度为O(1),基本还是不错的。

你可能感兴趣的:(42. 接雨水)