题目描述:
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1] 输出: 6
来源:https://leetcode-cn.com/problems/trapping-rain-water/
1 def trap2(height): 2 idx = 0 3 stack = [] # 存储遍历过的满足条件的元素索引 4 res = 0 # 存储结果 5 if len(height) < 3: return 0 # 如果height长度小于3,压根不可能构成容器,返回0即可 6 while idx < len(height): 7 while len(stack) > 0 and height[idx] > height[stack[-1]]: # 判断是否 可能 构成容器 8 top = stack.pop(-1) # 用来后面判断容器高度 9 if len(stack) == 0: # 说明stack只含有一个值(加上当前元素两个值),不可能构成容器,直接跳出即可! 10 break 11 else: # 构成了容器 12 h = min(height[stack[-1]], height[idx]) - height[top] # 计算容器可装水的高度 13 dist = idx - stack[-1] - 1 # 计算容器直径 14 res += (h * dist) # 可装水的容量 15 stack.append(idx) # 不可能构成容器时,当前元素索引入栈,指针右移 16 idx += 1 17 return res 18 19 20 print("--------测试trap2()--------") 21 height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1] 22 print(trap2(height))
总结:
我们在遍历数组时维护一个栈。如果当前的条形块小于或等于栈顶的条形块,我们将条形块的索引入栈,意思是当前的条形块被栈中的前一个条形块界定。如果我们发现一个条形块长于栈顶,我们可以确定栈顶的条形块被当前条形块和栈的前一个条形块界定,因此我们可以弹出栈顶元素并且累加答案到 ans ext{ans}ans
算法
使用栈来存储条形块的索引下标。
遍历数组:
当栈非空且 height[current]>height[st.top()] ext{height}[current]> ext{height}[st.top()]height[current]>height[st.top()]
意味着栈中元素可以被弹出。弹出栈顶元素 top ext{top}top。
计算当前元素和栈顶元素的距离,准备进行填充操作
distance=current−st.top()−1 ext{distance} = ext{current} - ext{st.top}() - 1distance=current−st.top()−1
找出界定高度
bounded_height=min(height[current],height[st.top()])−height[top] ext{bounded\_height} = min( ext{height[current]}, ext{height[st.top()]}) - ext{height[top]}bounded_height=min(height[current],height[st.top()])−height[top]
往答案中累加积水量ans+=distance×bounded_height ext{ans} mathrel{+}= ext{distance} imes ext{bounded\_height}ans+=distance×bounded_height
将当前索引下标入栈
将 current ext{current}current 移动到下个位置
作者:LeetCode
链接:https://leetcode-cn.com/problems/trapping-rain-water/solution/jie-yu-shui-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。