Intuition
Brute Force
- For each stock, check the ones before it until you find a previous stock not less than or equal to the current one.
Optimization
- We can achieve if we notice the following:
- The previously calculated span denotes the number of elements we can skip
- That is, if a previous stock is less than or equal to the current one, the current stock must be greater than or equal to all the stocks that stock is greater than equal to!
- And that amount to skip is the same as the span for that previous stock.
- We repeat this, concluding only if there are no stocks previous to the current one.
Note
I start at i = len(stack) - 1, since while I am at the first stock, there are no previous stocks/spans to compare to.
Question
Why do you additionally need to keep track of the prices?
Complexity
Runtime
- Each element can be only popped off once.
- There are 2 cases:
-
= previous
- Skip previously computed
- < previous
- We stop here
-
- Note that this is the ammortized cost. In the worst case, it will still be .
Space
Code
Just Stack
class StockSpanner:
def __init__(self):
self.stack = []
def next(self, price: int) -> int:
count = 1
while self.stack and price >= self.stack[-1][0]:
count += self.stack[-1][1]
self.stack.pop()
self.stack.append((price, count))
return count
# Your StockSpanner object will be instantiated and called as such:
# obj = StockSpanner()
# param_1 = obj.next(price)Keeping Count
class StockSpanner:
def __init__(self):
self.prices = []
self.stack = []
def next(self, price: int) -> int:
i = len(self.prices) - 1
count = 1
while i >= 0 and price >= self.prices[i]:
count += self.stack[i]
i -= self.stack[i]
self.prices.append(price)
self.stack.append(count)
return count
# Your StockSpanner object will be instantiated and called as such:
# obj = StockSpanner()
# param_1 = obj.next(price)Notes
Cards
START Basic Front: Online Stock Span Back:
END