363. 接雨水

363. 接雨水

中文English

给出 n 个非负整数,代表一张X轴上每个区域宽度为 1 的海拔图, 计算这个海拔图最多能接住多少(面积)雨水。

Trapping Rain Water

样例

样例 1:

输入: [0,1,0]
输出: 0

样例 2:

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

挑战

O(n) 时间, O(1) 空间

O(n) 时间, O(n) 空间也可以接受

输入测试数据 (每行一个参数)如何理解测试数据?
class Solution:
    '''
    大致思路:
    1.当前位置可以接雨水的数量 = min(左边最大值,右边最大值) - height(当前高度)
    2.得到当前位置左右两边最大值列表。最终得到结果。 
    '''
    def trapRainWater(self, heights):
        # write your code here
        #得到左,右最大值列表
        heights_l = [0] + heights + [0]
        left_l,right_l = [],[]
        left_max,right_max = 0,0
        for i in range(1,len(heights_l)-1):
            left_l.append(max(heights_l[:i+1]))
            right_l.append(max(heights_l[i:]))
        
        #开始计算各个位置可以接雨水的数量
        res = 0
        for j in range(len(heights)):
            res +=  min(left_l[j],right_l[j]) - heights[j]
        return res
        
#result = Solution().trapRainWater([0,1,0,2,1,0,1,3,2,1,2,1])
#print(result)

注:lintcode未通过,代码时间超过限制,max(heights_l[:i+1],取最大值需优化

优化之后:时间复杂度 O(n), 空间复杂度O(n)

class Solution:
    """
    @param heights: a list of integers
    @return: a integer
    """
    '''
    大致思路:
    1.当前位置可以接雨水的数量 = min(左边最大值,右边最大值) - height(当前高度)
    2.得到当前位置左右两边最大值列表。最终得到结果。 
    '''
    def trapRainWater(self, heights):
        left_l = []
        right_l = []
        l_max,r_max = -sys.maxsize,-sys.maxsize
        for i in heights:
            l_max = max(i,l_max)
            left_l.append(l_max)
        
        for j in reversed(heights):
            r_max = max(j,r_max)
            right_l.append(r_max)
        
        right_l = right_l[::-1]

        res = 0
        for z in range(len(heights)):
            res += min(left_l[z],right_l[z]) - heights[z]
        return res

 相向型双向指针算法:时间复杂度O(n), 空间复杂度O(1)

class Solution:
    """
    @param heights: a list of integers
    @return: a integer
    """
    '''
    大致思路:
    1.左指针 left_max < right_max
    不管当前位置在哪,只需要给出当前位置左边最大值,和右边假定最大值进行比较,如果left_max < right_max,则看左边是否可以接雨水
    left_max = max(left_max,当前位置高度)
    total += left_max - height  只有当前位置 [左边最大高度  右边假定最大高度] 中间才可以接雨水,left_max 来充当两边高度可以挡住的最小值
    2.右指针
    同上
    '''
    def trapRainWater(self, heights):
        if heights == []:
            return 0

        left_max,right_max = heights[0],heights[-1]
        total = 0
        left,right = 0,len(heights) - 1
        #在left < right 的时候成立,不能相等,否则left或者right会多走一步。(除非是left += 1放下面)
        while left < right:
            if left_max < right_max:#此时假定right_max 为右边可以挡住雨水的墙
                #从第二个位置开始看,第一个位置接不了水
                left += 1
                left_max = max(left_max,heights[left])
                total += left_max - heights[left] #如果左边有挡住的最大值墙,则可以接雨水
                
            else:##此时假定左边left_max 为左边可以挡住的墙
                #第二个位置开始看
                right -= 1
                right_max = max(right_max,heights[right])
                total += right_max - heights[right]
        return total

以当前位置为准,判断左右最大值的墙,计算当前位置可以接的雨水量

class Solution:
    '''
    大致思路:
    1.左指针 left_max < right_max
    不管当前位置在哪,只需要给出当前位置左边最大值,和右边假定最大值进行比较,如果left_max < right_max,则看左边是否可以接雨水
    left_max = max(left_max,当前位置高度)
    total += left_max - height  只有当前位置 [左边最大高度  右边假定最大高度] 中间才可以接雨水,left_max 来充当两边高度可以挡住的最小值
    2.右指针
    同上
    '''
    def trapRainWater(self, heights):
        if heights == []:
            return 0

        left_max,right_max = heights[0],heights[-1]
        total = 0
        left,right = 0,len(heights) - 1
        #在left <= right 的时候成立,当两者刚好相等,则跳出循环
        while left <= right:
            if left_max < right_max:#此时假定right_max 为右边可以挡住雨水的墙
                #以当前的位置为准,判断左边墙,出来在left += 1
                left_max = max(left_max,heights[left])
                total += left_max - heights[left] #如果左边有挡住的最大值墙,则可以接雨水
                left += 1
                
            else:##此时假定左边left_max 为左边可以挡住的墙
                right_max = max(right_max,heights[right])
                total += right_max - heights[right]
                right -= 1
        return total
原文地址:https://www.cnblogs.com/yunxintryyoubest/p/12866541.html