• [LeetCode] 42. Trapping Rain Water


    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.


    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!

    Example:

    Input: [0,1,0,2,1,0,1,3,2,1,2,1]
    Output: 6

    收集雨水。题意是给一个整数数组,数组包含的是一堆高度不同的bar,表示的是一个高度图(elevation map)。求此高度图能存水多少。这个题目有多种思路,此处我给出两种解法,一种双指针,一种单调栈。

    首先是双指针解法(two pointer)。思路是对于任意位置i,在i上的积水,是由其左右两边较矮的bar(可以想象为挡板)的高度和i位置的高度的差值决定的。即volume[i] = Math.min(Math.min(left[i], right[i]) - A[i]) * 1。这里的1是宽度。所以写代码的时候需要从左往右和从右往左各扫一遍,这样可以得出在每个位置上因着左边的bar和右边的bar的高度,能存水多少。代码如下,

    时间O(n)

    空间O(1)

    Java实现

     1 class Solution {
     2     public int trap(int[] height) {
     3         int left = 0;
     4         int right = height.length - 1;
     5         int res = 0;
     6         int leftMax = 0;
     7         int rightMax = 0;
     8         while (left < right) {
     9             if (height[left] < height[right]) {
    10                 leftMax = Math.max(height[left], leftMax);
    11                 res += leftMax - height[left];
    12                 left++;
    13             } else {
    14                 rightMax = Math.max(height[right], rightMax);
    15                 res += rightMax - height[right];
    16                 right--;
    17             }
    18         }
    19         return res;
    20     }
    21 }

    JavaScript实现

    /**
     * @param {number[]} height
     * @return {number}
     */
    var trap = function(height) {
        let left = 0;
        let right = height.length - 1;
        let res = 0;
        let leftMax = 0;
        let rightMax = 0;
        while (left < right) {
            if (height[left] < height[right]) {
                leftMax = Math.max(leftMax, height[left]);
                res += leftMax - height[left];
                left++;
            } else {
                rightMax = Math.max(rightMax, height[right]);
                res += rightMax - height[right];
                right--;
            }
        }
        return res;
    };

    再来是单调栈的解法。单调栈的思想可以参见84题。动图可以参考这个帖子。对于本题来说,我们寻求的是一个单调递减栈。栈内存的是数组的下标。当遇到一个元素比栈顶元素大的时候,就开始往外pop元素。这样被pop的坐标对应的水量其实是最低点,左挡板是最低点左边的一个index,右挡板是当前这个比栈顶元素大的高度。其他计算水量的步骤跟双指针没有区别。

    Java实现

     1 class Solution {
     2     public int trap(int[] height) {
     3         // corner case
     4         if (height == null || height.length == 0) {
     5             return 0;
     6         }
     7 
     8         // normal case
     9         Stack<Integer> stack = new Stack<>();
    10         int res = 0;
    11         for (int i = 0; i < height.length; i++) {
    12             while (!stack.isEmpty() && height[stack.peek()] < height[i]) {
    13                 int index = stack.pop();
    14                 // 如果栈顶元素一直相等,那么全都pop出去,只留第一个
    15                 while (!stack.isEmpty() && height[stack.peek()] == height[index]) {
    16                     stack.pop();
    17                 }
    18                 if (!stack.isEmpty()) {
    19                     int start = stack.peek();
    20                     res += (Math.min(height[start], height[i]) - height[index]) * (i - start - 1);
    21                 }
    22             }
    23             stack.add(i);
    24         }
    25         return res;
    26     }
    27 }

    JavaScript实现

     1 /**
     2  * @param {number[]} height
     3  * @return {number}
     4  */
     5 var trap = function (height) {
     6     // corner case
     7     if (height === null || height.length === 0) {
     8         return 0;
     9     }
    10 
    11     // normal case
    12     let stack = [];
    13     let res = 0;
    14     for (let i = 0; i < height.length; i++) {
    15         while (stack.length && height[stack[stack.length - 1]] < height[i]) {
    16             let index = stack.pop();
    17             while (
    18                 stack.length &&
    19                 height[stack[stack.length - 1]] == height[index]
    20             ) {
    21                 stack.pop();
    22             }
    23             if (stack.length) {
    24                 let start = stack[stack.length - 1];
    25                 res +=
    26                     (Math.min(height[start], height[i]) - height[index]) *
    27                     (i - start - 1);
    28             }
    29         }
    30         stack.push(i);
    31     }
    32     return res;
    33 };

    LeetCode 题目总结

  • 相关阅读:
    python基础(二)
    python基础(一)
    SQL的四种连接-左外连接、右外连接、内连接、全连接
    mysql常用操作
    jenkins邮件通知功能
    mysql常用命令
    SQL优化法则小记
    架构漫谈
    今日头条的成功史
    python连接mysql数据库简单例子
  • 原文地址:https://www.cnblogs.com/cnoodle/p/12156238.html
Copyright © 2020-2023  润新知