机试打卡 -05 接雨水(动态规划&栈)

文章讨论了三种方法来计算柱状图中能接收到的雨水量。第一种利用哈希表存储左右两侧最高柱子的高度,第二种采用动态规划,第三种使用单调栈。每种方法都关注如何确定每一列的雨水接收量,并提供了相应的算法实现细节。
摘要由CSDN通过智能技术生成

 


我的思路:依次计算每一列能接收的雨水量。
 

关键点:如何计算得到每一列所能接收到的雨水量?

        某一列能够接收到的雨水量,取决于其左右两侧最高的柱子。仅有当左右两侧的柱子均高于该列的高度,该列才可收到雨水,其雨水量为 min( left_height-h , right_height-h) 。

class Solution:
    def trap(self, height: List[int]) -> int:
        
        # height数组->对象属性
        self.height=height
        self.height_len=len(height)

        # 哈希表存储上一时刻的left_height与right_height
        Hash=dict()
        Hash['left_height']=0
        Hash['right_height']=max(height)
        self.Hash=Hash

        # rain_sum:总雨水量
        rain_sum=0

        # 依次计算每一个柱子所能接水的高度
        # i为索引
        for i in range(len(height)):
            # 传入柱子的索引
            rain_sum+=self.rain_calculate(i)
        return rain_sum
    
    def rain_calculate(self,index):

        # 取自身高度h
        h=self.height[index]

        # 左侧高度
        if index:
            left_height=max(self.Hash['left_height'],self.height[index-1])
        else:
            left_height=0

        # 右侧高度
        if self.height[index]!=self.Hash['right_height']:
            right_height=self.Hash['right_height']

        else:
            if index==self.height_len-1:
                right_height=0
            else:
                seq_temp=self.height[index+1:self.height_len]
                right_height=max(seq_temp)
        
        # 更新哈希表
        self.Hash['left_height']=left_height
        self.Hash['right_height']=right_height
        
        # 仅有当left_height和right_height均高于h时,该列才可接收到雨水
        if left_height>h and right_height>h:
            return min(left_height-h,right_height-h)
        
        else:
            return 0

    

关键点:哈希表存储上一时刻的left_height与right_height

为什么需要存储上一时刻的left_height与right_height?

        数组从左往右遍历,新柱子的 left_height 直接取 max(前一个柱子的left_height , 前一个柱子的高度),有些类似递归的思想。

        新柱子的 right_height 则分为两种情况,一种是 新柱子的高度不等于前一个柱子的 right_height,这种情况下则令新柱子的 right_height 直接取 前一个柱子的 right_height 即可;另一种情况则是 新柱子的高度等于前一个柱子的 right_height,即说明前一个柱子的 right_height 可能取自该根柱子,则新柱子的 right_height 取后面的柱子的最大值(数组切片) 即可。


思路2:动态规划

动态规划 - 复杂度分析

时间复杂度为:O(n)

空间复杂度为:O(n)


思路3:单调栈

class Solution:
    def trap(self, height: List[int]) -> int:

        ans = 0
        
        # 建立单调递减栈,用列表存储
        stack = list()
        
        # 从左向右依次遍历
        for i, h in enumerate(height):

            # 当栈不为空且h大于栈顶的高度时,进入while循环
            while stack and h > height[stack[-1]]:
                
                # 取出栈顶元素,作为低洼
                top = stack.pop()
                
                # 若取出栈顶元素后栈为空,则跳出while循环
                if not stack:
                    break
                
                # left为左边界的索引,i为右边界的索引
                left = stack[-1]
                currWidth = i - left - 1
                currHeight = min(height[left], height[i]) - height[top]
                ans += currWidth * currHeight
            
            # 循环结束后,将i加入栈中
            stack.append(i)
        
        return ans

关键点:单调递减栈

        考虑到低洼(可接雨水)必须有左右两侧边界,所以用python列表建立单调递减栈。当出现某一根柱子大于栈顶元素的高度时,开始进入内循环。出栈的top为低洼,根据left和right边界索引计算雨水存量,直到下一个栈顶大于等于h,方可跳出内循环。最后一定要将 i 入栈,因为 i 仍可能可以构成某一个低洼的左边界。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值