[Leetcode] 股票的价格跨度(单调栈)
题目链接:
496 下一个更大元素 I
901 股票价格跨度
先看一道单调栈相关的题目
下一个更大元素
nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置右侧的 第一个 比 x 大的元素。
两个没有重复元素的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。
对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1 。
返回一个长度为 nums1.length 的数组 ans 作为答案,满足 ans[i] 是如上所述的 下一个更大元素 。
示例 1:
输入:nums1 = [4,1,2], nums2 = [1,3,4,2].
输出:[-1,3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
- 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。
- 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
示例 2:
输入:nums1 = [2,4], nums2 = [1,2,3,4].
输出:[3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 2 ,用加粗斜体标识,nums2 = [1,2,3,4]。下一个更大元素是 3 。
- 4 ,用加粗斜体标识,nums2 = [1,2,3,4]。不存在下一个更大元素,所以答案是 -1 。
使用单调栈图解分析参考 https://leetcode.cn/problems/next-greater-element-i/solution/xia-yi-ge-geng-da-yuan-su-i-by-leetcode-bfcoj/
class Solution:
def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
res = {}
stack= []
for num in reversed(nums2):
while stack and stack[-1] <= num:
stack.pop()
res[num] = stack[-1] if stack else -1
stack.append(num)
return [res[x] for x in nums1]
股票的价格跨度
设计一个算法收集某些股票的每日报价,并返回该股票当日价格的跨度 。
当日股票价格的跨度定义为股价小于或等于今天价格的最大连续日数(从今天开始往回数,包括今天)。
例如,如果未来 7 天股票的价格是 [100,80,60,70,60,75,85],那么股票跨度将是 [1,1,1,2,1,4,6] 。
实现 StockSpanner 类:
StockSpanner() 初始化类对象。
int next(int price) 给出今天的股价 price ,返回该股票当日价格的跨度 。
示例:
输入:
["StockSpanner", "next", "next", "next", "next", "next", "next", "next"]
[[], [100], [80], [60], [70], [60], [75], [85]]
输出:
[null, 1, 1, 1, 2, 1, 4, 6]
解释:
StockSpanner stockSpanner = new StockSpanner();
stockSpanner.next(100); // 返回 1
stockSpanner.next(80); // 返回 1
stockSpanner.next(60); // 返回 1
stockSpanner.next(70); // 返回 2
stockSpanner.next(60); // 返回 1
stockSpanner.next(75); // 返回 4 ,因为截至今天的最后 4 个股价 (包括今天的股价 75) 都小于或等于今天的股价。
stockSpanner.next(85); // 返回 6
遍历(超时)
class StockSpanner:
def __init__(self):
self.prices = []
self.res = []
def next(self, price: int) -> int:
count = 1
for i in self.prices[::-1]:
if i <= price:
count += 1
else:
break
self.prices.append(price)
return count
# Your StockSpanner object will be instantiated and called as such:
# obj = StockSpanner()
# param_1 = obj.next(price)
单调栈
因为提交跑用例超出时间限制,emmm看答案使用了单调栈
和“下一个更大元素”类似,往前找到上一个最大元素,这之间的就是符合要求的天数(小于等于今日股价的连续天数),需要注意两点
首先,需要记录连续的天数,所以单调栈元素需要记录索引,可以结合元组实现(index,price)
其次,为了保证栈不为空,加入一个初始元素(-1,inf),索引-1,值无穷大(因此守护住栈底)
调用next 返回的连续个数就是前序更大元素index和当前元素index的差
class StockSpanner:
def __init__(self):
self.stack = [(-1, inf)]
self.idx = -1
def next(self, price: int) -> int:
self.idx += 1
#while self.stack and self.stack[-1][1] < price:
while self.stack[-1][1] <= price:
self.stack.pop()
self.stack.append((self.idx,price))
return self.idx - self.stack[-2][0]