算法-栈-每日温度
1 题目概述
1.1 题目出处
https://leetcode-cn.com/problems/daily-temperatures/
1.2 题目描述
根据每日 气温 列表,请重新生成一个列表,对应位置的输出是需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高,请在该位置用 0 来代替。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。
2 循环遍历
2.1 思路
最直观的,遍历所有元素,每次一次往后检查直到第一个比当前元素气温高的即求得气温升高所有天数。
2.2 代码
class Solution {
public int[] dailyTemperatures(int[] T) {
int[] result = new int[T.length];
for(int i = 0; i < T.length; i++){
for(int j = i + 1; j < T.length; j++) {
if(T[j] > T[i]){
result[i] = j-i;
break;
}
}
}
return result;
}
}
2.3 时间复杂度
O(N^2)
2.4 空间复杂度
O(1)
3 栈
3.1 思路
利用栈,如果栈为空或者当前元素比栈顶元素大,就将栈顶元素出栈并计算相应结果,然后继续比较下一个栈顶元素,直到当前元素不大于栈顶元素或栈为空。
最后将元素直接放入栈顶。
遍历完成后,还需要处理栈中元素,剩余的元素代表右侧没有比他们更高的气温了,所以升高气温天数都为0。
3.2 代码
class Solution {
public int[] dailyTemperatures(int[] T) {
int[] result = new int[T.length];
// 该int数字0位表示在原气温数组中位置,1位表示气温值
Stack<int[]> tmp = new Stack<>();
int[] top;
for(int i = 0; i < T.length; i++){
if(tmp.isEmpty()){
tmp.add(new int[]{i, T[i]});
}else{
while(!tmp.isEmpty()){
top = tmp.peek();
if(T[i] <= top[1]){
break;
}
// 当前数字大于栈顶就出栈
tmp.pop();
// 升高所需天数
result[top[0]] = i - top[0];
}
// 最后将当前数字入栈
tmp.add(new int[]{i, T[i]});
}
}
return result;
}
}
3.3 时间复杂度
O(N)
3.4 空间复杂度
O(N)
4 数组模拟栈
4.1 思路
思路和前面栈方法相同,只不过不用Stack类而是自己用数组模拟栈,减少了很多不必要的复杂操作开销。
4.2 代码
class Solution {
public int[] dailyTemperatures(int[] T) {
int[] result = new int[T.length];
// 该int数字0位表示在原气温数组中位置,1位表示气温值
int[][] tmp = new int[T.length][2];
int[] top;
// 标记tmp中当前应处理的行下标
int offset = -1;
for(int i = 0; i < T.length; i++){
while(offset > -1){
top = tmp[offset];
if(T[i] <= top[1]){
break;
}
offset--;
// 升高所需天数
result[top[0]] = i - top[0];
}
// 最后将当前数字入栈
tmp[++offset] = new int[]{i, T[i]};
}
return result;
}
}
4.3 时间复杂度
O(N)
4.4 空间复杂度
O(N)
5 倒序查找
5.1 思路
要求右侧第一个温度跟高的元素,所以其实从右往左找更方便。
而且,我们还加入一个快速判定方法,这里假设初始时j=i+1:
- T[i] < T[j]
显然result[i] = j - I; - T[i] >= T[j]且result[j] == 0,即i元素温度不低于j元素,但j元素右侧没有更高的温度,则i元素显然也不能在右侧升高温度:
result[i] = 0; - T[i] >= T[j]且result[j] > 0,即i元素温度不低于j元素,且j元素右侧有更高的温度,此时可通过
j = result[j] + j
快速找到第一个比j高的温度的下标,然后让i和这个新下表元素比较
5.2 代码
class Solution {
public int[] dailyTemperatures(int[] T) {
int[] result = new int[T.length];
result[T.length - 2] = 0;
for(int i = T.length - 2; i >= 0; i--){
int j = i + 1;
// 往右找第一个比i还大的
while(true){
if(T[i] < T[j]){
result[i] = j - i;
break;
}else if(result[j] == 0){
// 注意此时T[i] >= T[j]
result[i] = 0;
break;
} else{
// 注意此时T[i] >= T[j]且result[j] > 0
// 找到第一个比j高的温度的下标
j = result[j] + j;
}
}
}
return result;
}
}
5.3 时间复杂度
O(N)
5.4 空间复杂度
O(1)