Days until a warmer day
Given an array temps of daily temperatures, return an array
wait of the same length where wait[i] is the number of days after day
i until a strictly warmer day. If no later day is warmer, wait[i] is 0.
Examples
| Input | Output | Why |
|---|---|---|
temps = [73, 74, 75, 71, 69, 72, 76, 73] | [1, 1, 4, 2, 1, 1, 0, 0] | Day 2 (75) waits four days, until 76 on day 6. |
temps = [30, 40, 50, 60] | [1, 1, 1, 0] | Rising every day: each day waits one. |
temps = [50, 50, 50, 51] | [3, 2, 1, 0] | An equal temperature is not warmer. |
Constraints
- 1 ≤ n ≤ 10⁵
- 30 ≤ temps[i] ≤ 100
Hints
Hint 1
The direct approach scans forward from every day for the first warmer one. What is its worst case, and on what input?
Hint 2
When a warm day arrives, which earlier days does it settle? Only days that are still waiting, and only those cooler than it.
Hint 3
Keep the indices of days still waiting on a stack. Their temperatures never increase from bottom to top. A new day pops every waiting day cooler than itself, records the gap for each, then waits itself.
Dry run on [73,74,75,71,69,72,76,73]
Read it one frame at a time, the way you would trace the code on paper in an interview. Each frame shows the state after the step it describes.
-
Step 1 / 8temps730i741752713694725766737wait0001020304050607stack730waiting1
73 is not warmer than anything waiting. Day 0 joins the stack.
-
Step 2 / 8temps730741i752713694725766737wait1001020304050607stack740waiting1
74 is warmer than 73 (day 0). Pop it and record the wait: 1. Then day 1 waits.
-
Step 3 / 8temps730741752i713694725766737wait1011020304050607stack750waiting1
75 is warmer than 74 (day 1). Pop it and record the wait: 1. Then day 2 waits.
-
Step 4 / 8temps730741752713i694725766737wait1011020304050607stack750711waiting2
71 is not warmer than anything waiting (top is 75). Day 3 joins the stack.
-
Step 5 / 8temps730741752713694i725766737wait1011020304050607stack750711692waiting3
69 is not warmer than anything waiting (top is 71). Day 4 joins the stack.
-
Step 6 / 8temps730741752713694725i766737wait1011022314050607stack750721waiting2
72 is warmer than 69 (day 4) and 71 (day 3). Pop them and record the waits: 1, 2. Then day 5 waits.
-
Step 7 / 8temps730741752713694725766i737wait1011422314150607stack760waiting1
76 is warmer than 72 (day 5) and 75 (day 2). Pop them and record the waits: 1, 4. Then day 6 waits.
-
Step 8 / 8temps730741752713694725766737iwait1011422314150607stack760731waiting2
73 is not warmer than anything waiting (top is 76). Day 7 joins the stack.
How to think about it
The brute force looks forward from every day, which is O(n²) on a cooling
stretch where no day finds a warmer one quickly. Turn the question round: instead of each day
searching for its answer, let each new day hand out answers to the days that were waiting
for it.
Keep the indices of the days that have not yet seen a warmer day. When day i
arrives, every waiting day cooler than temps[i] has its answer: it is
i − j. Remove those days, then put i on the pile to wait.
Which waiting days are cooler? Always the most recent ones. A day can only still be waiting if nothing after it was warmer, so the waiting temperatures fall (or stay level) from oldest to newest. The cooler ones are all at the top, and you pop from the top until you meet one that is not cooler. That is a monotonic stack.
The while inside the for looks quadratic but is
not: every index is pushed once and popped at most once, so the total work over the whole loop is
at most 2n operations.
Complexity. Time O(n) · Space O(n)
The solution, in six languages
Each one is compiled and run against the test table before it is published. Java is reviewed by hand.
def next_warmer(temps):
wait = [0] * len(temps)
stack = [] # indices of days still waiting for a warmer one
for i, t in enumerate(temps):
while stack and temps[stack[-1]] < t:
j = stack.pop()
wait[j] = i - j # today is the first day warmer than day j
stack.append(i)
return wait # days never popped keep their 0#include <vector>
std::vector<int> solve(const std::vector<int>& temps) {
const int n = static_cast<int>(temps.size());
std::vector<int> wait(n, 0), stack; // stack holds indices still waiting
stack.reserve(n);
for (int i = 0; i < n; ++i) {
while (!stack.empty() && temps[stack.back()] < temps[i]) {
wait[stack.back()] = i - stack.back(); // first warmer day
stack.pop_back();
}
stack.push_back(i);
}
return wait;
}class Solution {
public int[] nextWarmer(int[] temps) {
int n = temps.length;
int[] wait = new int[n];
int[] stack = new int[n]; // indices still waiting; top is stack[top - 1]
int top = 0;
for (int i = 0; i < n; i++) {
while (top > 0 && temps[stack[top - 1]] < temps[i]) {
int j = stack[--top];
wait[j] = i - j; // first warmer day after j
}
stack[top++] = i;
}
return wait;
}
}function nextWarmer(temps) {
const wait = new Array(temps.length).fill(0);
const stack = []; // indices of days still waiting
for (let i = 0; i < temps.length; i++) {
while (stack.length && temps[stack[stack.length - 1]] < temps[i]) {
const j = stack.pop();
wait[j] = i - j; // today is the first warmer day after j
}
stack.push(i);
}
return wait;
}fn solve(temps: &[i32]) -> Vec<usize> {
let mut wait = vec![0usize; temps.len()];
let mut stack: Vec<usize> = Vec::new(); // indices still waiting
for i in 0..temps.len() {
while let Some(&j) = stack.last() {
if temps[j] >= temps[i] {
break;
}
wait[j] = i - j; // first warmer day after j
stack.pop();
}
stack.push(i);
}
wait
}-- Walk from the right. The stack holds (index, temperature) for the days still in view:
-- a day hidden behind a warmer, nearer day can never be anyone's answer.
solve :: [Int] -> [Int]
solve temps = snd (foldr step ([], []) (zip [0 ..] temps))
where
step (i, t) (stack, out) =
let stack' = dropWhile (\(_, u) -> u <= t) stack
w = case stack' of
((j, _) : _) -> j - i
[] -> 0
in ((i, t) : stack', w : out)
Where people lose marks
- Pushing temperatures instead of indices. You need the index to compute the gap, and you can always look the temperature up from it.
- Popping on
<=instead of<. An equal temperature is not warmer, so [50, 50, 51] would wrongly give the first day an answer of 1. - Assuming the answers come out in index order. They are filled in whenever a day is popped, so write into a pre-sized array rather than appending.
- Worrying that days left on the stack need special handling. They never saw a warmer day, and the array was initialised to 0, which is the right answer for them.
Variants to try
- Return the warmer temperature itself rather than the gap: store temps[i] instead of i − j when popping.
- The next warmer day to the left instead of the right: scan from the right, or keep the same stack and read the top after popping.
- The array is circular (after the last day comes the first): run the loop over 2n indices using i mod n, pushing only in the first pass.
- Stock span (how many consecutive previous days were at or below today): the same stack, reading the index left on top after popping.
Next problems
Balanced brackets
Every closing bracket must match the most recent unmatched opener. "Most recent" is what a stack gives you.
Open the problem → Hard25 minLargest rectangle in a bar chart
Each bar is the height of some rectangle. A stack finds, for every bar at once, how far it can stretch.
Open the problem →Write a solution and run it against the real test table.
Keep going
Balanced brackets
Every closing bracket must match the most recent unmatched opener. "Most recent" is what a stack gives you.
Open the problem → Hard25 minLargest rectangle in a bar chart
Each bar is the height of some rectangle. A stack finds, for every bar at once, how far it can stretch.
Open the problem → StackThe pattern behind it
Keep the elements whose question is still open; each new element settles the ones it beats and waits its turn.
Read the pattern →Preparing for a real process? Quant interview preparation, or book a free 20-minute call.