题目地址
题目描述
请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示: 气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。
题解
记录第一次出现的位置
- 构建一个存储每个温度第一次出现的位置
- 从后往前遍历,每遍历一个温度,就记录该温度第一次出现的位置
- 从
T+1开始到100找,这个区间的温度是否出现过,第一个出现温度的索引减去当前索引就是答案
class Solution {
public int[] dailyTemperatures(int[] T) {
int length = T.length;
int[] ans = new int[length];
int[] next = new int[101];
Arrays.fill(next, Integer.MAX_VALUE);
for (int i = length - 1; i >= 0; --i) {
int warmerIndex = Integer.MAX_VALUE;
for (int t = T[i] + 1; t <= 100; ++t) {
if (next[t] < warmerIndex) {
warmerIndex = next[t];
}
}
if (warmerIndex < Integer.MAX_VALUE) {
ans[i] = warmerIndex - i;
}
next[T[i]] = i;
}
return ans;
}
}
复杂度分析
-
时间复杂度:,其中 是温度列表的长度, 是数组 next 的长度,在本题中温度不超过 ,所以 的值为 。反向遍历温度列表一遍,对于温度列表中的每个值,都要遍历数组 next 一遍。
-
空间复杂度:,其中 是数组 next 的长度。除了返回值以外,需要维护长度为 的数组 next 记录每个温度第一次出现的下标位置。
单调栈
前面的方法是从后遍历,那么从前往后遍历怎么办呢?
从前往后遍历,还希望复杂度为 , 那么我们只能遍历一遍
对于 , 找到一个 , 使得 , 如果关注 ,那么就需要往后遍历找到 , 这样复杂度是 。如果关注 , 那么就是 之前的位置, 有哪些比 对应温度小的,这样只需要遍历一遍就行
class Solution {
public int[] dailyTemperatures(int[] T) {
int length = T.length;
int[] ans = new int[length];
Deque<Integer> stack = new LinkedList<Integer>();
for (int i = 0; i < length; i++) {
int temperature = T[i];
while (!stack.isEmpty() && temperature > T[stack.peek()]) {
int prevIndex = stack.pop();
ans[prevIndex] = i - prevIndex;
}
stack.push(i);
}
return ans;
}
}
复杂度分析
-
时间复杂度:,其中 是温度列表的长度。正向遍历温度列表一遍,对于温度列表中的每个下标,最多有一次进栈和出栈的操作。
-
空间复杂度:,其中 是温度列表的长度。需要维护一个单调栈存储温度列表中的下标。