[LeetCode][DP] Trapping Rain Water

Problem

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.

Water

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.

Solution

用两个数组,维护从左边到当前的元素最大高度,另外一个是从右边到当前元素的最大高度。当前元素的积水高度就取决于左右两边的较小值 - 当前元素高度。

Swift

class Solution {
  func trap(height: [Int]) -> Int {
    if height.count == 0 {
      return 0
    }
    var leftMax: [Int] = []
    var rightMax: [Int] = []
    var maxH = -1
    for h in height {
      leftMax.append(maxH)
      maxH = max(maxH, h)
    }
    maxH = -1
    for h in height.reverse() {
      rightMax.insert(maxH, atIndex: 0)
      maxH = max(maxH, h)
    }
    
    var ret : Int = 0
    for i in 0..<leftMax.count {
      let h = min(leftMax[i], rightMax[i])
      let water = max(0, h - height[i])
      ret += water
    }
    
    return ret
  }
}

另一种思路:Time: O(n), Space: O(1)
维护左右两个指针,然后朝里推进。于此同时,维护左右两边的最大高度。如果左边的较小,左边指针向右推进,然后根据左右两边最小的高度确定当前格子可以存多少水。这里的关键是,将左右两边更小的那个指针向里推进,有点像非递减序列地去填水。

Swift

class Solution {
  func trap(height: [Int]) -> Int {
    if height.count == 0 {
      return 0
    }
    var i = 0
    var j = height.count - 1
    var ret = 0
    var leftHeight = height[0]
    var rightHeight = height[j]
    while i < j {
      let minHeight = min(leftHeight, rightHeight)
      if (leftHeight < rightHeight) {
        i += 1
        let water = max(minHeight - height[i], 0)
        ret += water
        leftHeight = max(leftHeight, height[i])
      } else {
        j -= 1
        let water = max(minHeight - height[j], 0)
        ret += water
        rightHeight = max(rightHeight, height[i])
      }
    }
    
    return ret
  }
}

C++

class Solution {
public:
    /**
     * @param heights: a vector of integers
     * @return: a integer
     */
    int trapRainWater(vector<int> &heights) {
        if (heights.size() == 0) {
            return 0;
        }
        int i = 0;
        int j = heights.size() - 1;
        int leftHeight = heights[i];
        int rightHeight = heights[j];
        int ret = 0;
        while (i < j) {
            int minHeight = min(leftHeight, rightHeight);
            if (leftHeight < rightHeight) {
                i++;
                int water = max(minHeight - heights[i], 0);
                ret += water;
                leftHeight = max(leftHeight, heights[i]);
            } else {
                j--;
                int water = max(minHeight - heights[j], 0);
                ret += water;
                rightHeight = max(rightHeight, heights[j]);
            }
        }
        return ret;
    }
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,775评论 0 33
  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 3,479评论 3 44
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,466评论 25 708
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,809评论 1 92
  • 2017年4月28日 农历四月初三 星期五 晴 【早睡早起】 昨晚10:30睡,今早5:00起床。 【学佛】 1...
    陳境墨阅读 722评论 0 0