739. Daily Temperatures
Problem Description
You are given an array temperatures
where each element represents the daily temperature. For each day, you need to find how many days you would have to wait to get a warmer temperature.
Specifically, for each position i
in the array, you need to find the smallest number of days you'd have to wait after day i
to get a temperature that is strictly warmer than temperatures[i]
. If there's no future day with a warmer temperature, the answer for that position should be 0
.
For example, if temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
:
- For day 0 (temperature 73), the next warmer day is day 1 (temperature 74), so you wait 1 day
- For day 1 (temperature 74), the next warmer day is day 2 (temperature 75), so you wait 1 day
- For day 2 (temperature 75), the next warmer day is day 6 (temperature 76), so you wait 4 days
- For day 3 (temperature 71), the next warmer day is day 5 (temperature 72), so you wait 2 days
- And so on...
The result would be [1, 1, 4, 2, 1, 1, 0, 0]
.
The task is to return an array where each element represents the number of days to wait for a warmer temperature, or 0
if no warmer day exists in the future.
Intuition
The key insight is that we need to find the next greater element for each position in the array. When we think about this problem, we realize that as we traverse the array, we need to keep track of elements that are still "waiting" for a warmer day.
Consider traversing from right to left. At any position i
, we want to know which future days (to the right) could potentially be the answer. However, not all future days matter - if day j
has temperature 75 and day k
(where k > j
) has temperature 73, then day k
will never be the answer for any day before j
because day j
is both closer and warmer.
This observation leads us to maintain only the "relevant" future days - those that form an increasing temperature sequence when viewed from right to left. This is where the monotonic stack comes in.
By traversing from right to left and maintaining a stack of indices where temperatures are monotonically increasing (from stack top to bottom), we can efficiently find the next warmer day:
- When we're at position
i
, we pop all indices from the stack whose temperatures are less than or equal totemperatures[i]
(they're not useful anymore) - The remaining top of the stack (if it exists) is the closest day with a warmer temperature
- We then add the current index
i
to the stack for future positions to consider
The stack essentially filters out all the irrelevant days and keeps only those that could potentially be answers for elements we haven't processed yet. This reduces our search space and gives us an efficient O(n)
solution since each element is pushed and popped at most once.
Learn more about Stack and Monotonic Stack patterns.
Solution Approach
We implement the solution using a monotonic stack that traverses the array from right to left. The stack maintains indices of temperatures in monotonically increasing order (from top to bottom).
Here's the step-by-step implementation:
-
Initialize data structures:
- Create an empty stack
stk
to store indices - Create a result array
ans
of the same length astemperatures
, initialized with zeros - Get the length
n
of the temperatures array
- Create an empty stack
-
Traverse from right to left (
i
fromn-1
to0
):For each position
i
:a. Clean the stack: While the stack is not empty and the temperature at the top index is less than or equal to
temperatures[i]
, pop elements from the stack. This removes all days that are not warmer than the current day.while stk and temperatures[stk[-1]] <= temperatures[i]: stk.pop()
b. Find the answer: After cleaning, if the stack is not empty, the top element represents the nearest warmer day. Calculate the number of days to wait as
stk[-1] - i
.if stk: ans[i] = stk[-1] - i
c. Add current index: Push the current index
i
onto the stack for future iterations to consider.stk.append(i)
-
Return the result: After processing all elements, return the
ans
array.
The algorithm maintains the invariant that the stack contains indices in increasing order of their temperatures. This ensures that for any position, we can quickly find the next warmer day by looking at the stack top after removing all cooler or equal temperature days.
Time Complexity: O(n)
- Each element is pushed and popped from the stack at most once.
Space Complexity: O(n)
- In the worst case (decreasing temperatures), the stack could contain all indices.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a small example with temperatures = [72, 71, 75, 73, 70]
.
We'll traverse from right to left (index 4 to 0), maintaining a stack of indices.
Initial state:
stk = []
(empty stack)ans = [0, 0, 0, 0, 0]
(result array initialized with zeros)
Step 1: i = 4 (temperature = 70)
- Stack is empty, so no warmer day exists
ans[4] = 0
(remains 0)- Push index 4 to stack:
stk = [4]
- Current state:
ans = [0, 0, 0, 0, 0]
Step 2: i = 3 (temperature = 73)
- Check stack top:
temperatures[4] = 70 <= 73
, so pop index 4 - Stack becomes empty after popping
- No warmer day exists,
ans[3] = 0
- Push index 3 to stack:
stk = [3]
- Current state:
ans = [0, 0, 0, 0, 0]
Step 3: i = 2 (temperature = 75)
- Check stack top:
temperatures[3] = 73 <= 75
, so pop index 3 - Stack becomes empty after popping
- No warmer day exists,
ans[2] = 0
- Push index 2 to stack:
stk = [2]
- Current state:
ans = [0, 0, 0, 0, 0]
Step 4: i = 1 (temperature = 71)
- Check stack top:
temperatures[2] = 75 > 71
, so don't pop - Stack has index 2, so next warmer day exists
ans[1] = 2 - 1 = 1
(wait 1 day)- Push index 1 to stack:
stk = [2, 1]
- Current state:
ans = [0, 1, 0, 0, 0]
Step 5: i = 0 (temperature = 72)
- Check stack top:
temperatures[1] = 71 <= 72
, so pop index 1 - New stack top:
temperatures[2] = 75 > 72
, so don't pop - Stack has index 2, so next warmer day exists
ans[0] = 2 - 0 = 2
(wait 2 days)- Push index 0 to stack:
stk = [2, 0]
- Final state:
ans = [2, 1, 0, 0, 0]
Final Result: [2, 1, 0, 0, 0]
This means:
- Day 0 (72°): wait 2 days for 75°
- Day 1 (71°): wait 1 day for 75°
- Day 2 (75°): no warmer day
- Day 3 (73°): no warmer day
- Day 4 (70°): no warmer day
The monotonic stack efficiently maintains only the relevant indices, allowing us to find the next warmer day in constant time for each position.
Solution Implementation
1class Solution:
2 def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
3 # Stack to store indices of temperatures in descending order
4 stack = []
5 n = len(temperatures)
6 # Initialize result array with zeros
7 result = [0] * n
8
9 # Traverse temperatures from right to left
10 for i in range(n - 1, -1, -1):
11 # Pop elements from stack while current temperature is greater or equal
12 # This maintains a monotonic decreasing stack
13 while stack and temperatures[stack[-1]] <= temperatures[i]:
14 stack.pop()
15
16 # If stack is not empty, top element is the next warmer day
17 if stack:
18 result[i] = stack[-1] - i
19
20 # Add current index to stack for future comparisons
21 stack.append(i)
22
23 return result
24
1class Solution {
2 public int[] dailyTemperatures(int[] temperatures) {
3 int length = temperatures.length;
4 // Stack to store indices of temperatures in descending order
5 Deque<Integer> stack = new ArrayDeque<>();
6 int[] result = new int[length];
7
8 // Traverse the array from right to left
9 for (int currentIndex = length - 1; currentIndex >= 0; currentIndex--) {
10 // Remove all indices from stack where temperature is less than or equal to current
11 // These temperatures cannot be the next warmer day for current index
12 while (!stack.isEmpty() && temperatures[stack.peek()] <= temperatures[currentIndex]) {
13 stack.pop();
14 }
15
16 // If stack is not empty, top element is the index of next warmer temperature
17 // Calculate the difference in days
18 if (!stack.isEmpty()) {
19 result[currentIndex] = stack.peek() - currentIndex;
20 }
21 // If stack is empty, result[currentIndex] remains 0 (default value)
22
23 // Push current index to stack for future comparisons
24 stack.push(currentIndex);
25 }
26
27 return result;
28 }
29}
30
1class Solution {
2public:
3 vector<int> dailyTemperatures(vector<int>& temperatures) {
4 int n = temperatures.size();
5 stack<int> indexStack; // Stack to store indices of temperatures
6 vector<int> result(n); // Result array, initialized with 0s
7
8 // Traverse the temperatures array from right to left
9 for (int i = n - 1; i >= 0; --i) {
10 // Pop all indices from stack where temperature is less than or equal to current
11 // We're looking for the next warmer temperature
12 while (!indexStack.empty() && temperatures[indexStack.top()] <= temperatures[i]) {
13 indexStack.pop();
14 }
15
16 // If stack is not empty, the top contains the index of next warmer temperature
17 if (!indexStack.empty()) {
18 result[i] = indexStack.top() - i; // Calculate number of days to wait
19 }
20 // If stack is empty, result[i] remains 0 (no warmer day found)
21
22 // Push current index to stack for future comparisons
23 indexStack.push(i);
24 }
25
26 return result;
27 }
28};
29
1/**
2 * Given an array of daily temperatures, returns an array where each element
3 * represents the number of days until a warmer temperature.
4 * If there is no future day with warmer temperature, the value is 0.
5 *
6 * @param temperatures - Array of daily temperatures
7 * @returns Array where answer[i] is the number of days to wait for a warmer temperature
8 */
9function dailyTemperatures(temperatures: number[]): number[] {
10 const length = temperatures.length;
11 const result: number[] = new Array(length).fill(0);
12 const stack: number[] = []; // Monotonic decreasing stack storing indices
13
14 // Traverse the array from right to left
15 for (let currentIndex = length - 1; currentIndex >= 0; currentIndex--) {
16 // Pop elements from stack while they represent temperatures
17 // less than or equal to current temperature
18 while (stack.length > 0 &&
19 temperatures[stack[stack.length - 1]] <= temperatures[currentIndex]) {
20 stack.pop();
21 }
22
23 // If stack is not empty, the top element is the index of
24 // the next warmer day
25 if (stack.length > 0) {
26 result[currentIndex] = stack[stack.length - 1] - currentIndex;
27 }
28
29 // Push current index onto the stack for future comparisons
30 stack.push(currentIndex);
31 }
32
33 return result;
34}
35
Time and Space Complexity
Time Complexity: O(n)
The algorithm iterates through the temperatures array once from right to left. Although there's a nested while loop inside the for loop, each element is pushed onto the stack exactly once and popped at most once. This means that across the entire execution, the total number of operations for stack push and pop combined is at most 2n
. Therefore, the amortized time complexity is O(n)
, where n
is the length of the temperatures array.
Space Complexity: O(n)
The algorithm uses two additional data structures:
- The stack
stk
which in the worst case (when temperatures are in increasing order) can store alln
indices - The answer array
ans
which has exactlyn
elements
Both contribute to a space complexity of O(n)
, where n
is the length of the temperatures array.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Comparison Operator
One of the most common mistakes is using the wrong comparison operator when popping from the stack.
Incorrect Implementation:
# Wrong: using < instead of <= while stack and temperatures[stack[-1]] < temperatures[i]: stack.pop()
Why it's wrong: This would keep equal temperatures in the stack, but we need strictly warmer temperatures. If we keep equal temperatures, we might incorrectly identify a day with the same temperature as a "warmer" day.
Correct Implementation:
# Correct: using <= to remove equal temperatures too while stack and temperatures[stack[-1]] <= temperatures[i]: stack.pop()
2. Storing Values Instead of Indices
Another frequent error is pushing temperature values onto the stack instead of indices.
Incorrect Implementation:
stack = []
for i in range(n - 1, -1, -1):
while stack and stack[-1] <= temperatures[i]: # Wrong: comparing value with value
stack.pop()
if stack:
result[i] = ??? # Can't calculate days difference without indices!
stack.append(temperatures[i]) # Wrong: pushing value instead of index
Why it's wrong: We need indices to calculate the number of days between two positions. If we only store values, we lose positional information.
Correct Implementation:
stack = []
for i in range(n - 1, -1, -1):
while stack and temperatures[stack[-1]] <= temperatures[i]: # Compare values using indices
stack.pop()
if stack:
result[i] = stack[-1] - i # Calculate days using indices
stack.append(i) # Push index, not value
3. Wrong Traversal Direction with Incorrect Logic
Some might try traversing left-to-right but apply right-to-left logic, or vice versa.
Incorrect Implementation (mixing traversal directions):
# Traversing left to right but using right-to-left logic
for i in range(n): # Left to right
while stack and temperatures[stack[-1]] <= temperatures[i]:
stack.pop()
if stack:
result[i] = stack[-1] - i # This would give negative values!
stack.append(i)
Correct Alternative (Left-to-Right Approach):
stack = []
result = [0] * n
for i in range(n):
# Pop and update result for all indices waiting for current temperature
while stack and temperatures[stack[-1]] < temperatures[i]:
idx = stack.pop()
result[idx] = i - idx # Update the popped index's result
stack.append(i)
return result
In this left-to-right approach, we update the result when we find a warmer day, not when we process the original day. The logic is fundamentally different from the right-to-left approach.
Which data structure is used to implement priority queue?
Recommended Readings
Stack Intro Imagine you have a pile of books on your desk If you want to add a new book you place it on top If you want to read a book you take it from the top And if you simply want to see which book is on the top you
Monotonic Stack Deque Intro If you'd prefer a video div class responsive iframe iframe src https www youtube com embed Dq_ObZwTY_Q title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture web share allowfullscreen iframe div The word monotonic means a list or
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Don’t Miss This!