Daily Temperatures (LC 739)
On this page
Pattern: Monotonic Stack (next greater element, distance flavour)
Difficulty: Medium
Key Concept: Keep a stack of indices whose answer is still unknown, in decreasing temperature order. A warmer day resolves several of them at once.
Problem Statement
Given an array temperatures where temperatures[i] is the temperature on day i, return an
array answer such that answer[i] is the number of days you have to wait after day i
to get a warmer temperature. If there is no future day with a warmer temperature, answer[i] = 0.
Input: int[] temperatures, 1 <= n <= 10^5, 30 <= temperatures[i] <= 100
Output: int[] answer of the same length
Example
Input: [73, 74, 75, 71, 69, 72, 76, 73]
Output: [ 1, 1, 4, 2, 1, 1, 0, 0]
1. Algorithm & Pseudocode
Brute force
for i from 0 to n-1:
for j from i+1 to n-1:
if temps[j] > temps[i]:
answer[i] = j - i
break
return answer
Optimal (monotonic decreasing stack)
stack = empty stack of INDICES
answer = new int[n] // default 0 = "never gets warmer"
for i from 0 to n-1:
while stack not empty AND temps[stack.top] < temps[i]:
prev = stack.pop()
answer[prev] = i - prev // i is the first warmer day for prev
stack.push(i)
return answer // leftovers keep their default 0
2. Step-by-Step Analysis (Beginner-Friendly)
-
Why the brute force is wasteful For a decreasing run like
[100, 99, 98, 97], day 0’s inner loop scans the entire rest of the array and finds nothing. Then day 1 does almost the same scan. You are re-reading the same elements over and over. Atn = 10^5that’s ~5·10^9 comparisons — too slow. -
The observation that fixes it When you arrive at day
iwith temperature 76, that single value is the answer for every pending colder day you’ve seen — not just the previous one. So instead of each day searching forward, let each new day push its answer backwards to everyone waiting. -
Who is “waiting”? A day is waiting if you haven’t yet found anything warmer than it. Keep those days on a stack. Because you only keep days that are still unresolved, the temperatures on that stack are automatically decreasing from bottom to top — if a day were colder than the one below it, the one below would already have been resolved.
-
Why store indices, not temperatures The question asks “how many days”, which is a distance.
i - prevneedsprev’s position. Store indices and readtemps[index]whenever you need the value. -
Why it is O(n), not O(n²) The
whileloop is nested inside thefor, which looks quadratic. But each index is pushed exactly once and popped at most once. Across the entire run, thewhilebody executes at mostntimes total. Amortised, that’s O(1) work per day. -
What about days still on the stack at the end? They never found anything warmer.
answerwas initialised to all zeros, which is exactly the required output — no cleanup loop needed.
3. The Dry Run
Input: [73, 74, 75, 71, 69, 72, 76, 73]
| i | temp | Pops (index → answer) | Stack after (indices) | answer so far |
|---|---|---|---|---|
| 0 | 73 | — | [0] |
[0,0,0,0,0,0,0,0] |
| 1 | 74 | pop 0 → 1-0 = 1 |
[1] |
[1,0,0,0,0,0,0,0] |
| 2 | 75 | pop 1 → 2-1 = 1 |
[2] |
[1,1,0,0,0,0,0,0] |
| 3 | 71 | — (71 < 75) | [2,3] |
[1,1,0,0,0,0,0,0] |
| 4 | 69 | — (69 < 71) | [2,3,4] |
[1,1,0,0,0,0,0,0] |
| 5 | 72 | pop 4 → 5-4 = 1; pop 3 → 5-3 = 2; stop (72 < 75) |
[2,5] |
[1,1,0,2,1,0,0,0] |
| 6 | 76 | pop 5 → 6-5 = 1; pop 2 → 6-2 = 4 |
[6] |
[1,1,4,2,1,1,0,0] |
| 7 | 73 | — (73 < 76) | [6,7] |
[1,1,4,2,1,1,0,0] |
Leftover indices 6, 7 keep answer = 0. Final: [1,1,4,2,1,1,0,0] ✓
4. Java Solution
Brute Force
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
int n = temperatures.length;
int[] answer = new int[n];
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (temperatures[j] > temperatures[i]) {
answer[i] = j - i;
break; // first warmer day only
}
}
}
return answer;
}
}
Time O(n²) · Space O(1) extra
Optimal
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
int n = temperatures.length;
int[] answer = new int[n]; // default 0 handles "no warmer day"
Deque<Integer> stack = new ArrayDeque<>(); // indices, temps decreasing bottom→top
for (int i = 0; i < n; i++) {
// temperatures[i] is the first warmer day for every colder pending index
while (!stack.isEmpty() && temperatures[stack.peek()] < temperatures[i]) {
int prev = stack.pop();
answer[prev] = i - prev;
}
stack.push(i);
}
return answer;
}
}
Time O(n) — each index pushed once, popped ≤ once · Space O(n) worst case (strictly decreasing input keeps everything on the stack)
Bonus: O(1) extra space, scanning right → left
class Solution {
public int[] dailyTemperatures(int[] t) {
int n = t.length, hottest = 0;
int[] answer = new int[n];
for (int i = n - 1; i >= 0; i--) {
if (t[i] >= hottest) { hottest = t[i]; continue; } // no warmer day exists
int days = 1;
while (t[i + days] <= t[i]) days += answer[i + days]; // JUMP using known answers
answer[i] = days;
}
return answer;
}
}
Worth mentioning as a follow-up: it reuses already-computed answers to leapfrog. Still O(n) amortised, but O(1) auxiliary space.
5. The “Java vs. Others” Edge
ArrayDequeoverjava.util.Stack—StackextendsVector, so every operation issynchronizedand its iterator runs bottom-to-top (the opposite of stack order). The JDK’s ownStackjavadoc points you atDeque. Saying this unprompted is a senior signal.- Guard order matters:
!stack.isEmpty() && temperatures[stack.peek()] < ....ArrayDeque.peek()returnsnullwhen empty, and auto-unboxingnulltointthrows NPE. Java’s&&short-circuits, so the empty check must be first. new int[n]is zero-filled by the JVM — the language guarantees it. In C you’d needmemset; here the default is already the correct “no warmer day” answer.- Boxing cost:
Deque<Integer>boxes every index. Values 30–100 hit theIntegercache, but indices up to 10^5 do not. If asked to squeeze it, offerint[] stack = new int[n]; int top = -1;— same logic, zero allocation.
6. Complexity Summary
| Approach | Time | Space | Notes |
|---|---|---|---|
| Brute force | O(n²) | O(1) | TLE at n = 10^5 |
| Monotonic stack | O(n) | O(n) | Each index pushed/popped once |
| Right-to-left jump | O(n) | O(1) | Reuses answer[] to skip ahead |
Related Problems
| # | Problem | Same knob? |
|---|---|---|
| LC 496 | Next Greater Element I | next greater + HashMap indirection |
| LC 503 | Next Greater Element II | next greater, circular (2n loop) |
| LC 901 | Online Stock Span | previous greater, streaming |
| LC 84 | Largest Rectangle in Histogram | next/previous smaller |