七 单调栈
Images Source: https://realpython.com/
目录
来源
Datewhale33期__LeetCode 刷题 :
-
航路开辟者:杨世超
-
领航员:桐
-
航海士:杨世超、李彦鹏、叶志雄、赵子一
-
开源电子书
https://algo.itcharge.cn
1 基础知识
单调栈(Monotone Stack):一种特殊的栈。在栈的「先进后出」规则基础上,要求「从 栈顶 到 栈底 的元素是单调递增(或者单调递减)」。其中满足从栈顶到栈底的元素是单调递增的栈,叫做「单调递增栈」。满足从栈顶到栈底的元素是单调递减的栈,叫做「单调递减栈」。
单调栈的性质:
1.单调栈里的元素具有单调性
2.元素加入栈前,会在栈顶端把破坏栈单调性的元素都删除 ---- 直到满足单调
3.使用单调栈可以找到元素向左遍历第一个比他小的元素,也可以找到元素向左遍历第一个比他大的元素。
单调栈可以在时间复杂度为O(n)
的情况下,求解出某个元素左边或者右边第一个比它大或者小的元素。所以单调栈一般用于解决一下几种问题:
- 寻找左侧第一个比当前元素大的元素
- 寻找左侧第一个比当前元素小的元素
- 寻找右侧第一个比当前元素大的元素
- 寻找右侧第一个比当前元素小的元素
2 相关题目
2.1 503 . 下一个更大元素 II
- 思路: 环 >>>构建双倍长度的数组 >>> 利用单调递减栈记下索引
class Solution:
def nextGreaterElements(self, nums: List[int]) -> List[int]:
nums_2 = nums + nums
stack, ans = [], [-1 for _ in range(len(nums_2))]
for i in range(len(nums_2)):
while stack and nums_2[stack[-1]] < nums_2[i]:
ans[stack[-1]] = nums_2[i]
stack.pop()
stack.append(i)
return ans[:len(nums)]
2.2 316 . 去除重复字母
- 思路: 哈希去重 >>> 维护单调递增单调栈 >>> 并且单调栈内容
class Solution:
def removeDuplicateLetters(self, s: str) -> str:
stack, d = [], {}
for ch in s:
if ch not in d:
d[ch] = 1
else:
d[ch] += 1
for ch in s:
if ch not in stack:
while stack and stack[-1] > ch and d[stack[-1]] > 0:
stack.pop()
stack.append(ch)
d[ch] -= 1
return "".join(stack)
2.3 42 . 接雨水
- 思路 : 雨水两侧为空则填充, 碰到矩形则停止 >>>>> 递减单调栈
易知
水高度: min(height[left],height[i])−height[top]
水的宽度: i-stack[left] - 1
- 思路-----------单调栈
class Solution:
def trap(self, height: List[int]) -> int:
stack, ans, size = [], 0, len(height)
for i in range(size):
while stack and height[i] > height[stack[-1]]:
temp = height[stack[-1]]
stack.pop()
if not stack: break #如栈空停止while
ans += (min(height[i], height[stack[-1]]) - temp)*(i - stack[-1] - 1)
stack.append(i)
return ans