【面试】运算器-⑤每日温度

本文介绍了如何解决LeetCode中的每日温度问题,通过双重循环和使用栈实现,探索了不同数据结构如有序表和链表在解决该问题中的应用,以及作者从问题解决过程中的学习和反思。
摘要由CSDN通过智能技术生成

​​​​​​​739. 每日温度

感谢力扣 

给定一个整数数组 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)没有旺盛的好奇心,时间是一部分,另外一部分就是总觉得麻烦,不相信自己的基础,其实没有什么办法,懂不懂都得会,没有不会这个选项,关键就是要快。

        ② 思考还是被限制了,其实别人有逆向数组的方式,我觉得也是可以参考一下的,而且单调栈这个是我知识面的问题,逆向遍历这种就是思路问题了,世界上真的有很多很厉害的人,吾将上下而求索。

  • 30
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值