题目
根据每日 气温 列表,请重新生成一个列表,对应位置的输出是需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高,请在该位置用 0 来代替。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/daily-temperatures
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
- 理解题目以后,直接想到的思路就是 逐个遍历,然后对每个元素 向后遍历寻找比他大的元素,下标差 则是解,代码见1笨方法。
- 这种每个都去遍历的场景,很容易出现重复计算,由于是向右边找,如果想利用前面的计算成果,当然是从右边开始遍历啦。当右边的res数组已经计算完毕以后,如果你对i这个下标进行查找,
(1)发现 i+1符合要求,而i+1已经计算过了,则可以直接跨res[i+1] 个下标,继续匹配大小。就节省了重复的遍历,提高效率。
(2)如果你发现i+1不符合要求,并且 res[i+1]是0 ,请立马结束遍历,res[i] 必须是0(这个也是重点)。
代码见2.笨方法的优化 - 也可以使用栈来实现这个功能,如果你存储元素的值的话,当出栈以后。你不知道他下标是啥,就无法 对res赋值。所以更机智的办法就是直接在栈里存储下标,反正有数组。下标就能代表整个元素,完美! 由于是要 寻找比他大的元素,so,
(1)当遍历到的元素,比栈顶元素 大的时候,妥妥的出栈,然后求个下标差就好了嘛。不过这是其中一种场景
(2)如果遍历到的元素比栈顶小,就要先入栈,猥琐发育,别浪,(当然栈里面元素目前是单调递减哦)当遇到比栈顶大的以后,栈顶出栈!计算下标差,放入res数组。然后新栈顶来到pk台上,若遍历到的元素继续卫冕冠军,新栈顶出栈!直到栈内 没有元素了 或者 栈里元素更大,那卫冕冠军的下标就入栈咯。所以 for循环里面对栈的操作要是个while循环,(当栈内有元素并且栈顶元素比 目前遍历的元素小,要一直不停的比较,出栈)结束以后,当前遍历的元素下标入栈就好了嘛。结束!
1.笨方法
public int[] getRes(int [] T) {
int length = T.length;
int[] res = new int[length];
for(int i = 0;i < length;i++) {
for(int j = i+1; j < length;j++) {
if (T[j] > T[i]) {
res[i] = j-i;
break;
}
}
}
return res;
}
2.笨办法的优化
public int[] getRes(int [] T) {
int length = T.length;
int[] res = new int[length];
for(int i = length-2;i >= 0;i--) {
for(int j = i+1; j < length;j+=res[j) {
if (T[j] > T[i]) {
res[i] = j-i;
break;
} else if(res[j] == 0){
res[i] == 0;
break
}
}
}
return res;
}
3.单调栈 (知识点)
public int[] getRes(int [] T) {
int length = T.length;
int[] res = new int[length];
Stack<Integer> stack = new Stack();
for(int i =0;i < length;i++) {
while(!stack.isEmpty() && stack.peek() < T[i]) {
int peek = stack.peek();
res[peek] = i-peek;
stack.pop();
}
stack.push(T[i]);
}
return res;
}