leetcode(30)单调栈

6077. 巫师的总力量和

注意:因为要求连续,所以不能用回溯的方法做

496. 下一个更大元素 I

907. 子数组的最小值之和

class Solution:
    def sumSubarrayMins(self, arr: List[int]) -> int:
        res = 0
        stack = []
        arr = [-inf] + arr + [-inf]
        for r, a in enumerate(arr):
            while stack and arr[stack[-1]] > a:
                i = stack.pop()
                res += arr[i] * (i - stack[-1]) * (r - i)
            stack.append(r)
        return res % (10**9 + 7)

1856. 子数组最小乘积的最大值

前缀和+单调栈

class Solution:
    def maxSumMinProduct(self, nums: List[int]) -> int:
        pre_sum = [0]
        for i in range(len(nums)):
            pre_sum.append(nums[i] + pre_sum[i])
        res = 0
        nums = [-inf] + nums + [-inf]
        stack = []
        for r, n in enumerate(nums):
            while stack and nums[stack[-1]] > n:
                i = stack.pop()
                # print(nums[i])
                # print(nums[stack[-1]:r])
                cur = nums[i] * (pre_sum[r - 1] - pre_sum[stack[-1]])  # 注意r-1
                res = max(res, cur)
            stack.append(r)
        return res % (10 ** 9 + 7)

2104. 子数组范围和

使用两次单调栈,最大值和最小值分开求

class Solution:
    def subArrayRanges(self, nums: List[int]) -> int:
        res = 0
        new_nums = [-inf] + nums + [-inf]
        stack = []
        for r, n in enumerate(new_nums):
            while stack and new_nums[stack[-1]] > n:
                i = stack.pop()
                res -= new_nums[i] * (r - i) * (i - stack[-1])
            stack.append(r)

        new_nums = [inf] + nums + [inf]
        stack = []
        for r, n in enumerate(new_nums):
            while stack and new_nums[stack[-1]] < n:
                i = stack.pop()
                res += new_nums[i] * (r - i) * (i - stack[-1])
            stack.append(r)
        return res

901. 股票价格跨度

用单调栈维护一个单调递减的价格序列,并且对于每个价格,存储一个 weight 表示它离上一个价格之间(即最近的一个大于它的价格之间)的天数。
如果是栈底的价格,则存储它本身对应的天数。例如 [11, 3, 9, 5, 6, 4, 7] 对应的单调栈为 (11, weight=1), (9, weight=2), (7, weight=4)。

class StockSpanner:

    def __init__(self):
        self.stack = []

    def next(self, price: int) -> int:
        weight = 1
        while self.stack and self.stack[-1][0] <= price:
            weight += self.stack.pop()[1]
        self.stack.append((price, weight))
        return weight

173. 二叉搜索树迭代器

先把根节点及其左子树存入,然后依次出栈;每次调用next判断有右子树,则同样入栈

class BSTIterator:

    def __init__(self, root: Optional[TreeNode]):
        self.stack = []
        while root:
            self.stack.append(root)
            root = root.left

    def next(self) -> int:
        cur = self.stack.pop()
        node = cur.right
        while node:
            self.stack.append(node)
            node = node.left
        return cur.val

    def hasNext(self) -> bool:
        return len(self.stack) > 0

参考资料:
单调栈 + 前缀和的前缀和
前缀和 + 单调栈,拆成三个小问题逐步破解

posted @ 2022-10-22 19:52  YTT77  阅读(23)  评论(0编辑  收藏  举报