leetcode

42. 接雨水

2020-02-22  本文已影响0人  geaus

题目描述

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


image

示例:

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

解题思路

每个柱子可接的水量 = min(左边柱子高度,右边柱子高度) 与当前柱子高度的差。当然最左、最右柱子不可以接水。
所以可以定义两个数组left和right,分别存储i左边柱子的最大高度、i右边柱子的最大高度。

int trap(vector<int>& height){
    int length = height.size();
    if(length < 1)
        return 0;

    vector<int> left(length, 0);
    vector<Int> right(length, 0);

    int max_left = height[0];
    for(int i=1; i<length-1; i++){
        if(max_left<height[i])
            max_left = height[i];
        left[i] = max_left;
    }

    int max_right = height[length-1];
    for(int j=length-2; j>=0; j--){
        if(max_right<height[j])
            max_right = height[j];
        right[j] = max_right;
    }

    int ret = 0;
    for(int i=1; i<length-1; i++){
        int min_height = min(left[i], right[i]);
        ret += max(0, min_height-height[i]);
    }
    return ret;
}

更优解:双指针法,不需要设定left数组和right数组,仅保留max_left和max_right。这是因为计算每个位置的水量时,仅需要知道一边最小的高度就好。

    int trap(vector<int>& height) {
        int length = height.size();
        if(length<1)
            return 0;

        // max_left, 当前左边最大高度;max_right,当前右边最大高度
        int max_left = height[0], max_right = height[length-1];
        // left,当前左边收集下标;right,当前右边收集下标
        int left = 1, right = length - 2;
        int ret = 0;
        for(int i=1; i<length-1; i++){
            if(max_left<max_right){
                max_left = max(height[left], max_left);
                ret += max(0, max_left - height[left]);
                left++;
            }else{
                max_right = max(height[right], max_right);
                ret += max(0, max_right - height[right]);
                right--;
            }
        }
        
        return ret;
    }
上一篇下一篇

猜你喜欢

热点阅读