【LeetCode with Python】 Trapping Rain Water

博客域名: http://www.xnerv.wang
原题页面: https://oj.leetcode.com/problems/trapping-rain-water/
题目类型:两次遍历
难度评价:★★
本文地址: http://blog.csdn.net/nerv3x3/article/details/37339357

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!


将一个数列看成是一堆高低不一的蓄水墙,数值即这面墙的高度,求总的蓄水最大量。其实题目中的图就已经一目了然了,无需过多文字说明。
针对某一个x点,思考决定其蓄水量应该是该点左右两边分别出现过的最高的墙中的最小者决定的。例如,针对A=[0,1,0,2,1,0,1,3,2,1,2,1]这个例子,A[4]=1这一点,其左边出现过的最高墙是A[3]=2,其右边出现过的最高墙是A[7]=3,因此两者中的最小者就就是A[3]=2,因此A[4]的蓄水高度就是A[3]-A[4]=1,乘以底边1,即A[4]蓄水量为1。
针对每一个点去单独寻找这个最小值显然是不合理的,这样时间复杂度就是O(n*n)了。申请一个与原数组A等长的数组max_heights用来记录每个点的最大蓄水量,首先从左至右遍历一次A,记录当前遇到过的最大值,依次填入到max_heights中。然后再从右至左遍历一次A,也记录当前遇到过的最大值,与max_heights中对应位置的值进行比较,如果比max_heights中对应的值小,则替换掉max_heights中的值。通过这种方法,就能用2次时间复杂度为O(n)的遍历找出每个点的蓄水量,然后遍历max_heights,如果比A中对应的数值大的话,就累加其差值,最后得到的就是蓄水总量。也就是说,如果A中数值对max_heights中对应数值大,说明这个点无法蓄水。
空间复杂度为O(n),时间复杂度为O(n)。

class Solution:
    # @param A, a list of integers
    # @return an integer
    def trap(self, A):
        len_A = len(A)
        if 1 == len_A:
            return 0
        max_heights = [0] * len_A
        left_max = 0
        for i in range(0, len_A):
            if A[i] > left_max:
                left_max = A[i]
            max_heights[i] = left_max
        right_max = 0
        for i in range(len_A - 1, -1, -1):
            if A[i] > right_max:
                right_max = A[i]
            if right_max < max_heights[i]:
                max_heights[i] = right_max
        result = 0
        for i in range(0, len_A):
            if max_heights[i] > A[i]:
                result += (max_heights[i] - A[i])
        return result
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值