题目
根据每日 气温
列表,请重新生成一个列表,对应位置的输出是需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高,请在该位置用 0
来代替。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
,你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]
。
提示:气温
列表长度的范围是 [1, 30000]
。每个气温的值的均为华氏度,都是在 [30, 100]
范围内的整数。
解题思路
解法一:暴力法
从当前位置的下一个位置开始遍历数组,如果找到一个比当前元素大的值,就计算相差的天数;或者直到遍历完整个数组也没找到,那么相差的天数赋值为0,java中数组初始化时就是0,所以这步可以省略不写。
复杂度分析:
时间复杂度:O(n^2),对于数组中的每个元素,最坏情况下需要遍历其之后的每个元素,对于第 k 个元素,需要遍历之后的 n-k 个元素。总共需要 (n-1)+(n-2)+…+(n-k)…+(n-n) = n^2 -(1+2+…+n) = (n^2-n)/2 个元素,所以渐进时间复杂度为 O(n^2)。
空间复杂度:O(1),没有用到额外变量。
解法二:单调栈
维护一个存储下标的单调栈,从栈底到栈顶的下标对应的温度列表中的温度依次递减。如果一个下标在单调栈里,则表示尚未找到下一次温度更高的下标。
正向遍历温度列表。对于温度列表中的每个元素 T[i]:
1)如果栈为空,则直接将 i 进栈。
2)如果栈不为空,则比较栈顶元素 popId 对应的温度 T[popId] 和当前温度 T[i],如果 T[i] > T[popId],则将 popId 弹出,并将 popId 对应的等待天数赋为 i - popId。
3)重复上述操作直到栈为空或者栈顶元素对应的温度大于等于当前温度,然后将 i 进栈。
复杂度分析:
时间复杂度:O(n),其中 n 是温度列表的长度。正向遍历温度列表一遍,对于温度列表中的每个下标,最多有一次进栈和出栈的操作。
空间复杂度:O(n),其中 n 是温度列表的长度。需要维护一个单调栈存储温度列表中的下标。
代码
解法一:暴力法
class Solution {
public int[] dailyTemperatures(int[] T) {
int n = T.length;
int[] res = new int[n];
for(int i=0; i<n; i++){
for(int j=i+1; j<n; j++){
if(T[j]>T[i]){
res[i] = j-i;
break;
}
}
}
return res;
}
}
解法二:单调栈
class Solution {
public int[] dailyTemperatures(int[] T) {
int n = T.length;
int[] res = new int[n];
Deque<Integer> stack = new ArrayDeque<Integer>();
for(int i=0; i<n; i++){
// 栈顶元素小于当前元素,说明找到了一个目标值,那么就出栈
while(!stack.isEmpty() && T[stack.peekLast()] < T[i]){
int id = stack.removeLast();
res[id] = i-id;
}
// 如果栈为空,或者栈顶元素大于等于当前元素(满足单调递减关系),就将当前元素入栈
stack.addLast(i);
}
return res;
}
}