Problem
Write a class StockSpanner
which collects daily price quotes for some stock, and returns the span of that stock’s price for the current day.
The span of the stock’s price today is defined as the maximum number of consecutive days (starting from today and going backwards) for which the price of the stock was less than or equal to today’s price.
For example, if the price of a stock over the next 7 days were [100, 80, 60, 70, 60, 75, 85]
, then the stock spans would be [1, 1, 1, 2, 1, 4, 6]
.
Example 1:
Input: ["StockSpanner","next","next","next","next","next","next","next"], [[],[100],[80],[60],[70],[60],[75],[85]] Output: [null,1,1,1,2,1,4,6] Explanation: First, S = StockSpanner() is initialized. Then: S.next(100) is called and returns 1, S.next(80) is called and returns 1, S.next(60) is called and returns 1, S.next(70) is called and returns 2, S.next(60) is called and returns 1, S.next(75) is called and returns 4, S.next(85) is called and returns 6. Note that (for example) S.next(75) returned 4, because the last 4 prices (including today's price of 75) were less than or equal to today's price.
Note:
- Calls to
StockSpanner.next(int price)
will have1 <= price <= 10^5
. - There will be at most
10000
calls toStockSpanner.next
per test case. - There will be at most
150000
calls toStockSpanner.next
across all test cases. - The total time limit for this problem has been reduced by 75% for C++, and 50% for all other languages.
Solution 1: Brute Force (TLE)
Time complexity: O(n) per next call
Space complexity: O(n)
Solution 2: DP
dp[i] := span of prices[i]
j = i – 1
while j >= 0 and prices[i] >= prices[j]: j -= dp[j]
dp[i] = i – j
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// Author: Huahua, 144 ms class StockSpanner { public: StockSpanner() {} int next(int price) { if (prices_.empty() || price < prices_.back()) { dp_.push_back(1); } else { int j = prices_.size() - 1; while (j >= 0 && price >= prices_[j]) { j -= dp_[j]; } dp_.push_back(prices_.size() - j); } prices_.push_back(price); return dp_.back(); } private: vector<int> dp_; vector<int> prices_; }; |
Solution 3: Monotonic Stack
Maintain a monotonic stack whose element are pairs of <price, span>, sorted by price from high to low.
When a new price comes in
- If it’s less than top price, add a new pair (price, 1) to the stack, return 1
- If it’s greater than top element, collapse the stack and accumulate the span until the top price is higher than the new price. return the total span
e.g. prices: 10, 6, 5, 4, 3, 7
after 3, the stack looks [(10,1), (6,1), (5,1), (4,1), (3, 1)],
when 7 arrives, [(10,1), (6,1), (5,1), (4,1), (3, 1), (7, 4 + 1)] = [(10, 1), (7, 5)]
Time complexity: O(1) amortized, each element will be pushed on to stack once, and pop at most once.
Space complexity: O(n), in the worst case, the prices is in descending order.
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Author: Huahua class StockSpanner { public: StockSpanner() {} int next(int price) { int span = 1; while (!s_.empty() && price >= s_.top().first) { span += s_.top().second; s_.pop(); } s_.emplace(price, span); return span; } private: stack<pair<int, int>> s_; // {price, span}, ordered by price DESC. }; |
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// Author: Huahua class StockSpanner { private Stack<Integer> prices; private Stack<Integer> spans; public StockSpanner() { prices = new Stack<>(); spans = new Stack<>(); } public int next(int price) { int span = 1; while (!prices.empty() && price >= prices.peek()) { span += spans.pop(); prices.pop(); } prices.push(price); spans.push(span); return span; } } |
Python3
1 2 3 4 5 6 7 8 9 10 11 12 |
# Author: Huahua class StockSpanner: def __init__(self): self.s = list() def next(self, price): span = 1 while self.s and price >= self.s[-1][0]: span += self.s[-1][1] self.s.pop() self.s.append((price, span)) return span |
Related Problems
请尊重作者的劳动成果,转载请注明出处!花花保留对文章/视频的所有权利。
如果您喜欢这篇文章/视频,欢迎您捐赠花花。
If you like my articles / videos, donations are welcome.
[…] 花花酱 LeetCode 901. Online Stock Span […]