感谢力扣
给定一个整数数组
temperatures
,表示每天的温度,返回一个数组answer
,其中answer[i]
是指对于第i
天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用0
来代替。示例 1:
输入:temperatures
= [73,74,75,71,69,72,76,73] 输出: [1,1,4,2,1,1,0,0]示例 2:
输入: temperatures = [30,40,50,60] 输出: [1,1,1,0]示例 3:
输入: temperatures = [30,60,90] 输出: [1,1,0]提示:
1 <= temperatures.length <= 105
30 <= temperatures[i] <= 100
1.分析
这次是新题目了,我看看。是要求每个元素的下一个更大值的相对坐标,最大值填0,最简单的就是双重循环直接遍历一下,而且题目没有出现N这样的数字, 我觉得双重循环应该过不了时间判定,如果最坏情况除了最后一个都是一样的温度,最后一个温度是最大这样的话可太难受了,毕竟有105个元素。或者建立一个有序表来拿数据,但是我不知道有序表咋用的啊。不管了,先用双重循环试一下看看是不是时间复杂度不行吧:
① 编写代码看是否能够通过;
② 修改代码;
③ 如果有必要查一下有序表相关内容,写好代码;
④ 总结
2.编码
开始写代码了,初步测试了一下可以运行,学到了一招Arrays.stream操作,可以遍历输出数组,流操作也是后面需要用到的,下次多用用:
public int[] dailyTemperatures(int[] temperatures) {
int flag = 0;
int day = 0;
int[] result = new int[temperatures.length];
for(int i=0;i<temperatures.length;i++){
flag = 0;
day = 0;
for(int j=i+1;j<temperatures.length;j++){
day++;
if(temperatures[j]>temperatures[i]){
flag = 1;
break;
}
}
result[i] = flag == 1 ? day : 0;
}
return result;
}
果然,勿谓言之不预也,一大串99最后跟着一个100啊!
3.尝试
既然确实通不过(撞到了南墙,见到了黄河),首先用有序表尝试一下,有序表不行的情况下直接看题解,只有半个小时的时间做完这一题+写这篇记录了。
3.1 有序表尝试
左神算法笔记02:哈希表、有序表、链表_哈希表 有序-CSDN博客
感谢大佬
简单看了一下,不知道怎么找到下一个位置,可以通过key找到value在哪里,然后和当前下标做减法就可以了,应该可以到O(2n)的时间复杂度。实在是TreeMap没有这个方法的话,用链表应该也能做出来,话说JAVA的链表还没有试过,直接跳过去,去理解题解。
3.2 理解题解
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
int length = temperatures.length;
int[] ans = new int[length];
Deque<Integer> stack = new LinkedList<Integer>();
for (int i = 0; i < length; i++) {
int temperature = temperatures[i];
while (!stack.isEmpty() && temperature > temperatures[stack.peek()]) {
int prevIndex = stack.pop();
ans[prevIndex] = i - prevIndex;
}
stack.push(i);
}
return ans;
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/daily-temperatures/solutions/283196/mei-ri-wen-du-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
追加我认为的注释版本:
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
// 求温度数组的长度
int length = temperatures.length;
// 初始化结果数组
int[] ans = new int[length];
// Deque 双端队列(第一次用)LinkedList实现了list结构的Deque双端链表
// 所以这里为啥要用双端队列,直接用Stack不行吗?
Deque<Integer> stack = new LinkedList<Integer>();
// 遍历温度数组
for (int i = 0; i < length; i++) {
// 获取当天温度
int temperature = temperatures[i];
// 双端队列不为空 且 栈顶保存的下标对应的温度比当前温度要小 循环执行下面的语句
while (!stack.isEmpty() && temperature > temperatures[stack.peek()]) {
// 栈顶下标出栈
int prevIndex = stack.pop();
// 结果存结果数组 栈顶的下标对应的温度找到了比他大的温度的下标了,也就是当天温度的下标
// 距离就是当天温度的下标-栈顶下标
ans[prevIndex] = i - prevIndex;
}
// 要么没有备查的元素,要么前面的都比当天要大,这种情况就压栈
stack.push(i);
}
// 返回结果数组,应该这里的初值就是0了。
return ans;
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/daily-temperatures/solutions/283196/mei-ri-wen-du-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
3.3 自己打一遍
按照题解的思路自己写了一下,用了Stack,看看什么情况
public int[] dailyTemperatures(int[] temperatures) {
Stack<Integer> stack = new Stack<Integer>();
int[] result = new int[temperatures.length];
for(int i=0;i<temperatures.length;i++){
while(!stack.isEmpty() && temperatures[stack.peek()]<temperatures[i]){
result[stack.peek()] = i - stack.peek();
stack.pop();
}
stack.push(i);
}
return result;
}
好的,用例通过了,为什么这么大差距
为什么题解只要24ms,我就要227ms啊,相当于十倍了好吗,换一个数据结构这么大差别吗?
Deque<Integer> stack = new LinkedList<Integer>();
今天下午午休以后我再看一下Stack和Deque和LinkedList的区别,不可思议
4.总结
这个应该是第一个我自己没有做出来的题目了,链表的思路是可取的,确实最后的题解也是用的下标的方式,总体来说还是比较巧妙的,总结两个缺点吧:
① 对新事务(对没有错就是Deque)没有旺盛的好奇心,时间是一部分,另外一部分就是总觉得麻烦,不相信自己的基础,其实没有什么办法,懂不懂都得会,没有不会这个选项,关键就是要快。
② 思考还是被限制了,其实别人有逆向数组的方式,我觉得也是可以参考一下的,而且单调栈这个是我知识面的问题,逆向遍历这种就是思路问题了,世界上真的有很多很厉害的人,吾将上下而求索。