力扣901(java&python)-股票价额跨度(中等)

题目:

编写一个 StockSpanner 类,它收集某些股票的每日报价,并返回该股票当日价格的跨度。

今天股票价格的跨度被定义为股票价格小于或等于今天价格的最大连续日数(从今天开始往回数,包括今天)。

例如,如果未来7天股票的价格是 [100, 80, 60, 70, 60, 75, 85],那么股票跨度将是 [1, 1, 1, 2, 1, 4, 6]。

 示例:

输入:["StockSpanner","next","next","next","next","next","next","next"], [[],[100],[80],[60],[70],[60],[75],[85]]
输出:[null,1,1,1,2,1,4,6]
解释:
首先,初始化 S = StockSpanner(),然后:
S.next(100) 被调用并返回 1,
S.next(80) 被调用并返回 1,
S.next(60) 被调用并返回 1,
S.next(70) 被调用并返回 2,
S.next(60) 被调用并返回 1,
S.next(75) 被调用并返回 4,
S.next(85) 被调用并返回 6。

注意 (例如) S.next(75) 返回 4,因为截至今天的最后 4 个价格
(包括今天的价格 75) 小于或等于今天的价格。
 

提示:

调用 StockSpanner.next(int price) 时,将有 1 <= price <= 10^5。
每个测试用例最多可以调用  10000 次 StockSpanner.next。
在所有测试用例中,最多调用 150000 次 StockSpanner.next。
此问题的总时间限制减少了 50%。

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

解题思路:

这是今天的每日一题,我不会做,害,看了题解区各位大佬的题解,这里记录一下~

单调栈:

题目的意思可以转换为,对于当日的价格,从这个价格开始往前查找,找到第一个比这个价格高的价格,这两个价格的下标差就是当日价格的跨度。

利用单调栈维护一个从栈底到栈顶单调递减的栈,栈中每个元素存放的是[price, count],price表示价格,count表示跨度。每次调用到next(price)时,就会比较当前price与栈顶的price,如果栈顶价格小于等于当前价格,则将栈顶的跨度加上当前价格的跨度,然后将栈顶元素出栈,直到栈顶价格大于当前价格或者栈为空。

图解来自@【Lemon】

java代码:

 1 class StockSpanner {
 2     Deque<int[]> stack = new ArrayDeque<>();
 3 
 4     public StockSpanner() {
 5 
 6     }
 7     
 8     public int next(int price) {
 9         int count = 1;
10         while(!stack.isEmpty() && stack.peek()[0] <= price){
11             count += stack.pop()[1];
12         }
13         stack.push(new int[]{price, count});
14         return count;
15     }
16 }
17 
18 /**
19  * Your StockSpanner object will be instantiated and called as such:
20  * StockSpanner obj = new StockSpanner();
21  * int param_1 = obj.next(price);
22  */

 python3代码:

 1 class StockSpanner:
 2 
 3     def __init__(self):
 4         self.stack = []
 5 
 6     def next(self, price: int) -> int:
 7         count = 1
 8         while self.stack and self.stack[-1][0] <= price:
 9             count += self.stack.pop()[1]
10         self.stack.append((price, count))
11         return count
12 
13 
14 # Your StockSpanner object will be instantiated and called as such:
15 # obj = StockSpanner()
16 # param_1 = obj.next(price)

 小知识:

单调栈:存放的数据是有序的

  • 单调递增栈:就是从栈底到栈顶数据是从大到小
  • 单调递减栈:就是从栈底到栈顶数据是从小到大

单调栈的伪代码:

 1 stack<int> st;
 2 //此处一般需要给数组最后添加结束标志符
 3 for (遍历这个数组)
 4 {
 5     if (栈空 || 栈顶元素大于等于当前比较元素)
 6     {
 7         入栈;
 8     }
 9     else
10     {
11         while (栈不为空 && 栈顶元素小于当前元素)
12         {
13             栈顶元素出栈;
14             更新结果;
15         }
16         当前数据入栈;
17     }
18 }

 

posted on 2022-10-21 11:06  我不想一直当菜鸟  阅读(39)  评论(0编辑  收藏  举报