• Trapping Rain Water


    Date:

      Nov. 2, 2017

    Problem:

      https://leetcode.com/problems/trapping-rain-water/description/

    Description:

      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!

      

      一开始想了很多扯淡的方法,其中比较可行的一种是向右遍历,检查到新高度时向右扫描这层水的体积(寻找一个大于等于这一高度的,姑且叫做“墙”吧)。

      不过这种方法对于一枝独秀的高墙,对,没错,比如上面的height[8],尤其是当它是height[0]的时候,需要额外讨论很多东西。于是懒癌患者被直接劝退了。

      所以修改了一下这个方法的思路,现在我们使用两个指针l(左指针)和r(右指针)来向中间扫描。

      注意,直接计算水的体积十分麻烦,所以我们用一种简化的思路:

        用block记录总的方块数,这只需要一次扫描。

        用water记录不考虑方块占空间的水体积,这可以在接下来的扫描中计算出来。

        最后,我们返回water - block,也就是水的真实体积。

      我们看到,不考虑方块占空间的话,水的体积呈现出一个极好的(或者两个)实心阶梯”形状“。这使我们很方便的计算它的量。

      我们用lh表示已知的左侧墙高,用rh表示已知的右侧墙高,用wh表示目前水平面高度。初始状态下,它们的值都是0。

      当lh <= rh的时候,我们试图向右扫描一堵更高的左墙来装下更多的水。我们将lh的值更新为扫描到的第一堵更高的左墙。将这个过程中增加的水量加入water:

    water += (r - l + 1)*(min(lh, rh) - wh)

      注意,这些水是“一层一层”地“叠放”起来的。

      然后更新水平面高度。

    wh = min(lh, rh)

      当lh > rh时,做类似向左扫描加水操作。

      l,r指针交错时,返回结果。

      这个算法复杂度为O(N)。

      以下是submission。

     1 class Solution:
     2     def trap(self, height):
     3         l = 0
     4         r = len(height) - 1
     5         lh = 0
     6         rh = 0
     7         wh = 0
     8         water = 0
     9         block = 0
    10         for i in height:
    11             block += i
    12         while l < r:
    13             if lh <= rh:
    14                 while l < r and height[l] <= lh:
    15                     l += 1
    16                 lh = height[l]
    17                 water += (r - l + 1)*(min(lh, rh) - wh)
    18                 wh = min(lh, rh)
    19             else:
    20                 while l < r and height[r] <= rh:
    21                     r -= 1
    22                 rh = height[r]
    23                 water += (r - l + 1)*(min(lh, rh) - wh)
    24                 wh = min(lh, rh)
    25         return max(water - block, 0)

      另附“竖放”水层的算法,用C++实现。作者mcrystal。

    class Solution {
    public:
        int trap(int A[], int n) {
            int left=0; int right=n-1;
            int res=0;
            int maxleft=0, maxright=0;
            while(left<=right){
                if(A[left]<=A[right]){
                    if(A[left]>=maxleft) maxleft=A[left];
                    else res+=maxleft-A[left];
                    left++;
                }
                else{
                    if(A[right]>=maxright) maxright= A[right];
                    else res+=maxright-A[right];
                    right--;
                }
            }
            return res;
        }
    };
  • 相关阅读:
    utils:一个通用枚举类
    代码片段(二):SQL片段
    Scala:(一) 特点及安装环境配置
    Scala:(二) 语言基础-数据结构、表达式(判断、循环、块表达式)
    11-docker搭建mysql一主一从
    10-docker搭建rabbitmq集群
    尚硅谷周阳面试第二季
    docker 修改mysql 表大小写铭感
    volatile的理解
    消息队列优缺点及其选型
  • 原文地址:https://www.cnblogs.com/neopolitan/p/7774708.html
Copyright © 2020-2023  润新知