LeetCode 42. Trapping Rain Water

来源:互联网 发布:怎么骂网络喷子 编辑:程序博客网 时间:2024/04/28 13:45

1. 题目描述

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!

2. 解题思路

我们的基本思路呢, 就是找到这个数组从左向右递增的的位置, 同时找到从右向左的递增位置, 然后根据这些递增位置之间所形成的区间, 计算存储的水的量的多少。

3. code

class Solution {public:    int trap(vector<int>& height) {        if (height.size() <= 1)            return 0;        // 找到递增 与 递减的关键节点        vector<int> incr_pos_l, incr_pos_r;        int mymax = 0;        for (int i = 0; i != height.size(); i++){            if (height[i] > mymax){                incr_pos_l.push_back(i);                mymax = height[i];            }        }        mymax = 0;        for (int i = height.size() - 1; i >= 0; i--){            if (height[i] > mymax){                incr_pos_r.push_back(i);                mymax = height[i];            }        }        // 计算水容量        int voll = computeVal(incr_pos_l, height, true);        int volr = computeVal(incr_pos_r, height, false);        int val = 0;        for (int j = incr_pos_l.back(); j != incr_pos_r.back(); j++){            val += height[incr_pos_l.back()] - height[j];        }        return voll + volr + val;    }private:    void myincr(int & i, bool isLeft){        isLeft ? i++ : i--;    }    int computeVal(vector<int> incr_pos, vector<int>& height, bool isLeft){        int sum = 0;        for (int i = 0; i < incr_pos.size() - 1; i++){            int val = 0;            for (int j = incr_pos[i]; j != incr_pos[i + 1]; myincr(j, isLeft)){                val += height[incr_pos[i]] - height[j];            }            sum += val;        }        return sum;    }};

4. 大神解法

4.1 demo1 两端逼近

两端逼近, 找到他们两端的所记录到的最大值, 并计算存储的水量

Keep track of the maximum height from both forward directions backward directions, call them leftmax and rightmax.public int trap(int[] A){    int a=0;    int b=A.length-1;    int max=0;    int leftmax=0;    int rightmax=0;    while(a<=b){        leftmax=Math.max(leftmax,A[a]);        rightmax=Math.max(rightmax,A[b]);        if(leftmax<rightmax){            max+=(leftmax-A[a]);       // leftmax is smaller than rightmax, so the (leftmax-A[a]) water can be stored            a++;        }        else{            max+=(rightmax-A[b]);            b--;        }    }    return max;}

4.2 demo2

Keep track of the already safe level and the total water so far. In each step, process and discard the lower one of the leftmost or rightmost elevation.CChanging the given parameters to discard the lower border. I'm quite fond of this one.int trap(int* height, int n) {    int level = 0, water = 0;    while (n--) {        int lower = *height < height[n] ? *height++ : height[n];        if (lower > level) level = lower;        water += level - lower;    }    return water;}Slight variation with two pointers (left and right).int trap(int* height, int n) {    int *L = height, *R = L+n-1, level = 0, water = 0;    while (L < R) {        int lower = *L < *R ? *L++ : *R--;        if (lower > level) level = lower;        water += level - lower;    }    return water;}C++With left and right index.int trap(vector<int>& height) {    int l = 0, r = height.size()-1, level = 0, water = 0;    while (l < r) {        int lower = height[height[l] < height[r] ? l++ : r--];        level = max(level, lower);        water += level - lower;    }    return water;}With left and right iterator.int trap(vector<int>& height) {    auto l = height.begin(), r = height.end() - 1;    int level = 0, water = 0;    while (l != r + 1) {        int lower = *l < *r ? *l++ : *r--;        level = max(level, lower);        water += level - lower;    }    return water;}
0 0
原创粉丝点击