代码随想录文章讲解
单调栈
- 遍历2遍list(因为
nums是circular integer array),下标都是i % len(nums)
- 剩下的与739. 每日温度类似
class Solution:
def nextGreaterElements(self, nums: List[int]) -> List[int]:
n = len(nums)
ans = [-1] * n
mono_stack = []
for i in range(2*n):
while mono_stack and nums[mono_stack[-1]] < nums[i%n]:
prev_index = mono_stack.pop()
ans[prev_index] = nums[i%n]
mono_stack.append(i%n)
return ans
代码随想录文章讲解
双指针(Time limit exceeded)
- 首先,如果按照列来计算的话,宽度一定是1了,我们再把每一列的雨水的高度求出来就可以了。 可以看出每一列雨水的高度,取决于,该列 左侧最高的柱子和右侧最高的柱子中最矮的那个柱子的高度。
- 每列雨水的高度为
min(lHeight, rHeight) - height
- 只要从头遍历一遍所有的列,然后求出每一列雨水的体积,相加之后就是总雨水的体积了。
- 要注意第一个柱子和最后一个柱子不接雨水
class Solution:
def trap(self, height: List[int]) -> int:
res = 0
for i in range(len(height)):
if i == 0 or i == len(height) - 1:
continue
height_left = height[i-1]
height_right = height[i+1]
for r in range(i+2, len(height)):
if height[r] > height_right:
height_right = height[r]
for l in range(i-2, -1, -1):
if height[l] > height_left:
height_left = height[l]
h = min(height_left, height_right) - height[i]
if h > 0:
res += h
return res
DP
- 思路与双指针一致,我们把每一个位置的左边最高高度记录在一个数组上(maxLeft),右边最高高度记录在一个数组上(maxRight)。这样就避免了重复计算,这就用到了动态规划。
- 当前位置,左边的最高高度是前一个位置的左边最高高度和本高度的最大值。即从左向右遍历:
maxLeft[i] = max(height[i], maxLeft[i - 1]);从右向左遍历:maxRight[i] = max(height[i], maxRight[i + 1]);这样就找到递推公式。
class Solution:
def trap(self, height: List[int]) -> int:
if len(height) <= 2:
return 0
res = 0
max_left = [0] * len(height)
max_left[0] = height[0]
max_right = [0] * len(height)
max_right[-1] = height[-1]
for l in range(1,len(height)):
max_left[l] = max(max_left[l-1], height[l])
for r in range(len(height)-2, -1, -1):
max_right[r] = max(max_right[r+1], height[r])
for i in range(len(height)):
h = max(min(max_left[i], max_right[i]) - height[i], 0)
res += h
return res
单调栈
- 首先单调栈是按照行方向来计算雨水
- 使用单调栈内元素的顺序: 从栈头(元素从栈头弹出)到栈底的顺序应该是从小到大的顺序。因为一旦发现添加的柱子高度大于栈头元素了,此时就出现凹槽了,栈头元素就是凹槽底部的柱子,栈头第二个元素就是凹槽左边的柱子,而添加的元素就是凹槽右边的柱子。
- 遇到相同的元素,更新栈内下标,就是将栈里元素(旧下标)弹出,将新元素(新下标)加入栈中。因为我们要求宽度的时候 如果遇到相同高度的柱子,需要使用最右边的柱子来计算宽度。
- 是用单调栈,其实是通过 长 * 宽 来计算雨水面积的。长就是通过柱子的高度来计算,宽是通过柱子之间的下标来计算,那么栈里有没有必要存一个pair<int, int>类型的元素,保存柱子的高度和下标呢。其实不用,栈里就存放int类型的元素就行了,表示下标,想要知道对应的高度,通过height[stack.top()] 就知道弹出的下标对应的高度了。
class Solution:
def trap(self, height: List[int]) -> int:
stack = [0]
result = 0
for i in range(1, len(height)):
while stack and height[i] > height[stack[-1]]:
mid_height = stack.pop()
if stack:
h = min(height[stack[-1]], height[i]) - height[mid_height]
w = i - stack[-1] - 1
result += h * w
stack.append(i)
return result