单调栈
最后更新于
这有帮助吗?
最后更新于
这有帮助吗?
单调栈:栈中元素按递增或递减顺序排列
单调栈优点:时间复杂度是线性的,每个元素只遍历一次
单调栈主要回答这样的几种问题
比当前元素更大的下一个元素
比当前元素更大的前一个元素
比当前元素更小的下一个元素
比当前元素更小的前一个元素
_ = input()
nums = [int(x) for x in input().split(" ")]
stk = list()
ans = [-1] * len(nums)
for i, num in enumerate(nums):
if not stk:
stk.append(num)
continue
while stk and stk[-1] >= num:
stk.pop()
if stk:
ans[i] = stk[-1]
stk.append(num)
print(ans)
from typing import List
class Solution:
# 方法1
def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
stk, d = list(), dict()
for num in nums2:
# 找到右边第一个(后一个)比它大的数
while stk and stk[-1] < num:
d[stk.pop()] = num
stk.append(num)
return [d.get(num, -1) for num in nums1]
func nextGreaterElement(nums1 []int, nums2 []int) []int {
var stk []int
var mp = make(map[int]int)
for _, v := range nums2 {
for len(stk) > 0 && v > stk[len(stk)-1] {
mp[stk[len(stk)-1]] = v
stk = stk[:len(stk)-1]
}
stk = append(stk, v)
}
for _, v := range stk {
mp[v] = -1
}
var ans []int
for _, v := range nums1 {
ans = append(ans, mp[v])
}
return ans
}
from typing import List
class Solution:
def nextGreaterElements(self, nums: List[int]) -> List[int]:
ans = [-1] * len(nums)
stk = list()
nums2 = nums + nums
for i, num in enumerate(nums2):
# 找到第i个数的下一个比它大的元素
while stk and nums[stk[-1]] < num:
ans[stk.pop()] = num
# 这里需要判断所维护的单调栈是否重复添加nums中的元素
if i < len(nums):
stk.append(i)
return ans
from typing import List
"""
请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。
如果气温在这之后都不会升高,请在该位置用 0 来代替。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。
"""
"""
分析:找到下一个比当前元素a值大的元素b,b_idx - a_idx即为所求
"""
class Solution:
def dailyTemperatures(self, T: List[int]) -> List[int]:
ans = [0] * len(T)
stk = list()
for i, num in enumerate(T):
while stk and T[stk[-1]] < num:
# 在右边找到了第一个比"当前位置"T[stk[-1]]大的元素
ti = stk.pop()
ans[ti] = i - ti
stk.append(i)
return ans
from typing import List
class Solution:
def trap(self, height: List[int]) -> int:
ans = 0
stk = list()
for i in range(len(height)):
while stk and height[stk[-1]] < height[i]: # 形成了凹槽
ti = stk.pop()
while stk and height[stk[-1]] == height[ti]: # 中间一段是“平滑的”
stk.pop()
if stk:
ans += (i - stk[-1] - 1) * (min(height[stk[-1]], height[i]) - height[ti])
stk.append(i)
return ans
# 参考:https://mp.weixin.qq.com/s/f9ebzbwymR8jQeUDxjeCDA
class StockSpanner:
def __init__(self):
self.stk = list()
def next(self, price: int) -> int:
ans = 1
while self.stk and self.stk[-1][0] <= price:
ans += self.stk.pop()[-1]
self.stk.append((price, ans))
return ans