720220119_datawhale33期_leetcode刷题_7单调栈

七 单调栈

720220119_datawhale33期_leetcode刷题_7单调栈_第1张图片Images Source: https://realpython.com/

目录

  • 七 单调栈
        • 来源
    • 1 基础知识
    • 2 相关题目
      • 2.1 [503 . 下一个更大元素 II](https://leetcode-cn.com/problems/next-greater-element-ii/)
      • 2.2 [316 . 去除重复字母](https://leetcode-cn.com/problems/remove-duplicate-letters/)
      • 2.3 [42 . 接雨水](https://leetcode-cn.com/problems/trapping-rain-water/)

来源

Datewhale33期__LeetCode 刷题 :

  • 航路开辟者:杨世超

  • 领航员:桐

  • 航海士:杨世超、李彦鹏、叶志雄、赵子一

  • 开源内容
    https://github.com/itcharge/LeetCode-Py

  • 开源电子书
    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 . 接雨水

  • 思路 : 雨水两侧为空则填充, 碰到矩形则停止 >>>>> 递减单调栈

720220119_datawhale33期_leetcode刷题_7单调栈_第2张图片

易知
水高度: 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

你可能感兴趣的:(算法,leetcode,算法)