2Brute2Best
🔥0

Stock Span Problem

Easy·GeeksforGeeksBasic Anchor
GeeksforGeeks
30-Second Mental ModelMonotonic Stack (decreasing, previous greater) — span / dominance
Complexity:O(N²)→O(N)
Key Insight

Keep a stack of indices whose prices strictly decrease from bottom to top. For each day, pop every index whose price is ≤ today's. The top that is left is the closest earlier day with a higher price, so span = i − top (or i + 1 if the stack is empty). Then push today.

Core Validity Invariant

A day stays on the stack only while no later day has a price ≥ it. Such a later day hides it from everyone after, so it can never stop a span again.

01

Problem

You are given the price of a stock on n days in a row, in the array arr.

The span of a day is the number of days in a row, ending with that day and going backwards, on which the price was less than or equal to that day's price. The day itself always counts, so every span is at least 1.

Return the span of every day. Write it as vector<int> calculateSpan(vector<int>& arr).

Input

An integer array arr of length n: the price on each day.

Output

An array of n numbers: the span of each day, in order.

Example 1
Input: arr = [100, 80, 60, 70, 60, 75, 85]
Output: [1, 1, 1, 2, 1, 4, 6]

On day 5 the price is 75. Going back: 60, 70, 60 are all ≤ 75, then 80 is higher. So the span is 4 (days 2, 3, 4 and 5). On day 6 the price is 85: everything back to 100 is ≤ 85, so the span is 6.

Example 2
Input: arr = [10, 4, 5, 90, 120, 80]
Output: [1, 1, 2, 4, 5, 1]

On day 3 the price is 90, and all three earlier prices are lower, so the span is 4. On day 5 the price 80 is lower than the 120 just before it, so the span is 1.

Constraints
  • • 1 ≤ n ≤ 10^5
  • • 1 ≤ arr[i] ≤ 10^5
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    When I walk backwards from day i, what exactly makes me stop?

  2. 2.

    If I knew the index of that stopping day, how would I get the span from it?

  3. 3.

    Does a price equal to today's stop the span, or is it counted?

  4. 4.

    Day j is earlier than day i and has a lower (or equal) price. Can day j ever be the stopping day for a day after i?

  5. 5.

    So which earlier days are still worth remembering at any moment?

03

Brute force approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceFor each day, step backwards while the price is ≤ today'sO(N²)O(1)
OptimalKeep a stack of days with decreasing prices; pop everything ≤ todayO(N)O(N)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “days in a row, going backwards”We need the distance to a boundary on the left — the first day that breaks the run.
  • “less than or equal to that day's price”The run stops at the first **strictly greater** price → previous greater element, with `≤` being popped.
  • “span of every day”We need this boundary for all n days, so it must be cheap each time → monotonic stack.
For each element+how far back do the ≤ values go+stop at the previous strictly greater→Monotonic Stack (decreasing, previous greater) — span / dominance

This is the anchor of the span sub-pattern. It is the same decreasing stack as Next Greater Element, but read the other way: instead of recording an answer for the popped elements, we record the answer for the new element, using whatever is left on top. The span is just i − prevGreater. The next question (Online Stock Span) has no array to look back into, so it keeps the span inside the stack instead of an index.

10

Don't make this mistake

Popping only while the price is strictly smaller
✗ while (!st.empty() && arr[st.back()] < arr[i]) st.pop_back();
✓ while (!st.empty() && arr[st.back()] <= arr[i]) st.pop_back();

Equal prices are part of the span. With <, an equal price stays on the stack and stops the span too early: [5, 5, 5] would give [1, 1, 1] instead of [1, 2, 3].

Forgetting the empty-stack case
✗ span[i] = i - st.back();
✓ span[i] = st.empty() ? i + 1 : i - st.back();

If every earlier price is ≤ today, the stack is empty and the span covers all days from 0 to i, which is i + 1 days. Calling back() on an empty vector is undefined behaviour.

Storing prices instead of indices
✗ st.push_back(arr[i]);
✓ st.push_back(i);

The span is a distance, so you need to know where the higher price was. Store the index and read the price with arr[st.back()].

Recording the answer for the popped element

Pattern confusion with Next Greater Element: there, when arr[i] pops j, you record nge[j] = arr[i]. Here the question is about the previous greater of i, so the popped days get nothing — the answer for i comes from the top after all the pops.

11

Want to implement this?

Write it yourself on GeeksforGeeks, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like Monotonic Stack translate into production architectures and low-level memory mechanics.