InterviewPrepKit

Home / Coding / Stack

Online Stock Span

medium Original ↗
Solving tips
  • Insight: once a day's price is beaten by a later higher price it can never stop a future backward walk, so merge dominated days into the day that dominates them.
  • Keep a monotonic decreasing stack of (price, span) pairs; on next(price) pop every pair with price <= new price, summing their spans into the new day's span.
  • Start span = 1 (today counts) before absorbing popped spans, and pop on <= not < so equal prices extend the span.
  • Store (price, span) pairs, not bare prices, or you lose the shadowed-day counts; complexity is amortized O(1) per call (not worst-case) with O(n) space.

Problem

Design a class StockSpanner that receives a stream of daily stock prices, one per call. Each time a new price arrives via next(price), return that day’s span: the number of consecutive days ending today (today included) on which the price was less than or equal to today’s price.

In other words, starting from today and walking backward, count how many days in a row have price <= today's price, stopping at the first strictly greater price.

Implement:

  • StockSpanner() — initializes the object.
  • next(price: int) -> int — records today’s price and returns today’s span.

Examples

Example 1

Calls: next(100), next(80), next(60), next(70), next(60), next(75), next(85) Output: 1, 1, 1, 2, 1, 4, 6 Explanation: for 75, the run of days with price ≤ 75 is [60, 70, 60, 75], so the span is 4; 80 stops it.

Example 2

Calls: next(10), next(20), next(30) Output: 1, 2, 3 Explanation: each new price beats everything before it, so the span keeps growing.

Example 3

Calls: next(50), next(50) Output: 1, 2 Explanation: “less than or equal” means an equal price extends the span.

Constraints

  • 1 <= price <= 10^5
  • At most 10^4 calls to next — so an O(n) per call rescan is borderline O(n²) overall and the intended solution is amortized O(1) per call.

Think about it first

Hint 1 Once a day's price is dominated by a later, higher price, that earlier day can never again be the "first strictly greater price" for any future query. Do you still need it individually?
Hint 2 Keep a stack of days that are still "visible" — i.e., days whose price hasn't been beaten yet. What does the stack look like from bottom to top?
Hint 3 Store `(price, span)` pairs on a stack kept in strictly decreasing price order. When a new price arrives, pop every pair with `price <= new price`, summing their spans into the new day's span; then push `(new price, total span)`.
Your workspace Not runnable by design — this is your interview scratchpad. Saved on this device.