Daily Temperatures

This question feels simple. For each day, how long until a warmer day? But the slow answer rescans the future for every single day. The fast answer uses a clever stack that only ever moves forward. This is the question that teaches the monotonic stack pattern.

🎯 The Problem

You get a list of daily temperatures. For each day you answer one thing: how many days until a warmer day arrives?

  • Each value in the list is a temperature for one day.
  • For each day, count the days you wait until a warmer day shows up.
  • Return a list of those waits, one per day.
  • If no warmer day ever comes, that day’s answer is 0.

A quick read of [73, 74, 75, 71, 69, 72, 76, 73]. Day 0 is 73. The next day is 74, which is warmer. So the wait is 1. Day 3 is 71. The warmer day is 72 at index 5. So the wait is 2. The last day has nothing warmer ahead, so it is 0.

Input: temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
Output: [1, 1, 4, 2, 1, 1, 0, 0]
Explanation: each number is how many days until a warmer temperature.

Here is the question drawn for a few days. The arrow points to the next warmer day.

+1

+2

none

day0: 73

day1: 74

day3: 71

day5: 72

day6: 76

0

🐒 Approach 1: Look Ahead Every Day (Brute Force)

For each day, scan forward until you hit a warmer day.

The idea:

  • Stand on each day in turn.
  • Look at every day after it.
  • Stop at the first day that is warmer.
  • The wait is the gap in days. If none is warmer, the wait is 0.

Why it is weak:

  • For each day you may scan most of the rest of the list.
  • A list that keeps getting colder forces a near full scan every time.
  • Time is O(nΒ²), where n is the number of days. Too slow on a long list.

Here is the look-ahead code:

daily_temperatures_brute_force.py
def daily_temperatures(temperatures):
answer = [0] * len(temperatures)
for i in range(len(temperatures)):
for j in range(i + 1, len(temperatures)):
if temperatures[j] > temperatures[i]:
answer[i] = j - i
break
return answer

⚑ Approach 2: Monotonic Stack (Best)

The idea in one line: keep a stack of days still waiting for warmth, and settle each one the moment a warmer day arrives.

The idea:

  • A monotonic stack is a stack kept in one fixed order. Here the temperatures only decrease from bottom to top.
  • Store the index of each waiting day, not its temperature. The index lets us measure the gap later.

How it works:

  • Walk the days once with their index.
  • Compare today with the day on top of the stack.
  • While today is warmer than that top day, pop it. Its wait is today’s index minus the popped index.
  • Keep popping while today is warmer than the new top. Then push today’s index.

Why it is fast:

  • Each index is pushed once and popped at most once.
  • So even with the inner loop the total work is O(n).

Here is a dry run on the first few values [73, 74, 75, 71]. Watch the stack of indices change.

start: stack empty

i=0 t=73: push, stack=[0]

i=1 t=74 warmer than 73: pop 0 ans[0]=1, push 1, stack=[1]

i=2 t=75 warmer than 74: pop 1 ans[1]=1, push 2, stack=[2]

i=3 t=71 colder: push 3, stack=[2,3]

Steps to Solve

  1. Make an answer list filled with zeros, one slot per day.
  2. Make an empty stack to hold indices of waiting days.
  3. Walk through the days with their index.
  4. While the stack is not empty and today is warmer than the day on top, pop that index and set its answer to today’s index minus the popped index.
  5. Push today’s index onto the stack.
  6. After the last day, any indices still on the stack keep their answer of zero.

This Python version uses a list as the stack of indices and a list of zeros for the answers.

daily_temperatures.py
def daily_temperatures(temps):
n = len(temps)
answer = [0] * n # default wait is zero
stack = [] # holds indices of waiting days
for i in range(n):
# while today is warmer than the day on top of the stack
while stack and temps[i] > temps[stack[-1]]:
prev = stack.pop() # that day's wait is over
answer[prev] = i - prev # gap in days
stack.append(i) # today waits for its warmer day
return answer
temps = [73, 74, 75, 71, 69, 72, 76, 73]
print(daily_temperatures(temps))

The output of the above code will be:

[1, 1, 4, 2, 1, 1, 0, 0]

Let us read the Python version line by line and understand why each line is there.

The line answer = [0] * n makes a list of zeros, one per day. Zero is the right default. If a day never finds a warmer day, its answer stays zero. So we never have to handle that case again. The line stack = [] is our pile of waiting day indices. We store indices, not temperatures. We need the index so we can compute the gap later.

The loop for i in range(n) reads each day. The inner while stack and temps[i] > temps[stack[-1]] is the engine. The part stack[-1] peeks at the top index without removing it. temps[stack[-1]] is the temperature of that waiting day. So we keep going while today is warmer than the top waiting day. Inside, prev = stack.pop() removes that index, because today is its warmer day. Then answer[prev] = i - prev records the wait as the gap in days. The while loop can pop several days at once, because today might be warmer than several waiting days.

After the while loop ends, stack.append(i) puts today on the stack. Today now waits for its own warmer day. Each index is pushed once and popped at most once. That is why this reads each day only a couple of times, giving O(n) total.

⏱️ Time and Space Complexity

The brute force rescans the future for each day, so it is O(nΒ²). The monotonic stack pushes and pops each index at most once, so even with the inner while loop the total work is O(n). The stack can hold up to n indices in the worst case, like a list that keeps getting colder. So the space is O(n).

Approach Time Complexity Space Complexity
Brute force look ahead O(nΒ²) O(1)
Monotonic stack O(n) O(n)

Tip

Store indices on the stack, not temperatures. You need the index to compute the wait as today’s index minus the waiting index. Storing the temperature alone loses that information.

🧩 Key Takeaways

  • βœ… For each day you want the number of days until a warmer day, or zero if none.
  • βœ… A monotonic stack holds indices of days still waiting for warmth.
  • βœ… When today is warmer than the top day, pop it and record the gap in days.
  • βœ… Store indices, not temperatures, so you can compute the wait.
  • βœ… Each index is pushed and popped once, so the total time is O(n).

Check Your Knowledge

4 questions Show quiz Hide quiz

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What does Daily Temperatures ask for each day?

    Why: For each day you return how many days you wait until a warmer day, and zero when none comes.

  2. 2

    What does the optimal solution store on the stack?

    Why: It stores indices, because the index is needed to compute the wait as today's index minus the waiting index.

  3. 3

    Why is a monotonic stack O(n) overall despite the inner while loop?

    Why: Every index enters and leaves the stack at most one time, so the total push and pop work is O(n).

  4. 4

    What is the default answer for a day that never gets warmer?

    Why: We fill the answer list with zeros, so any day with no warmer future day stays zero.

πŸš€ What’s Next?