LeetCode-901-股票价格跨度

题目描述:编写一个 StockSpanner 类,它收集某些股票的每日报价,并返回该股票当日价格的跨度。
今天股票价格的跨度被定义为股票价格小于或等于今天价格的最大连续日数(从今天开始往回数,包括今天)。
例如,如果未来7天股票的价格是 [100, 80, 60, 70, 60, 75, 85],那么股票跨度将是 [1, 1, 1, 2, 1, 4, 6]。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/online-stock-span
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


本题仍然使用从栈底到栈顶(从大到小)顺序的单调栈来维护各个价格之间的顺序。
在类的init方法内准备一个单调栈和一个price数组。next方法的开始和普通的单调栈用法一致,如果不满足条件就退栈,当满足条件时就把当前元素进栈。
在这里,我们重点讲解的是如何判断连续的价格低于当日价格的天数。如下图,我们假定有三个位置ijk,对应的元素为nums[i]nums[j]nums[k](下边描述的nums[k],nums[j]进栈只是为了直观的展示元素之间大小,代码中进栈出栈的是元素索引)。

  1. 如果k位置元素进栈,使得整个栈为空,说明k位置之前的元素都小于等于k位置元素。
    反证:假定在[0:k-1]范围上存在一个位置j,使得nums[j] >=nums[k],那么当nums[k]进栈时,nums[j]一定会被留在栈内,但事实是栈内没有元素,所以可得矛盾
  2. 如果k位置元素进栈,没有元素出栈,说明栈内元素都大于k位置元素,结果也就是1
  3. 如果k位置元素进栈,造成大量元素出栈但是栈并没有为空,我们假定现在栈顶索引为i,那么就可以确定[i:k]范围里的全部元素都一定小于等于nums[k],结果就为k位置减去栈顶元素位置。
    反证:假定在[i:k-1]范围内存在一个位置j,使得nums[j] > nums[k],那么当nums[k]进栈时,退栈到j位置就要结束了,因为nums[j]>nums[k],但事实并非如此,与假定情况矛盾
    在这里插入图片描述
class StockSpanner:
    def __init__(self):
        # 单调栈
        self.mon_stack = list()
        # 单调栈记录索引(日期),prices记录所有的价格
        self.prices = list()

    def next(self, price: int) -> int:
        self.prices.append(price)
        while self.mon_stack and self.prices[self.mon_stack[-1]] <= price:
            self.mon_stack.pop()
        self.mon_stack.append(len(self.prices)-1)
        # 如果除了刚进栈的元素,其他元素都出栈了
        # 说明当前索引i之前的元素都小于它
        if len(self.mon_stack) == 1:
            return len(self.prices)
        else:
            return len(self.prices) - self.mon_stack[-2] - 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值