【百日算法计划】:每日一题,见证成长(023)

题目

每日温度

请根据每日气温列表,重新生成一个列表,对应的位置的输出为:要想观测到更高的气温,至少需要等待的天数.如果气温在这之后都不再升高,则该位置用0代替.
例如,给定一个列表[73, 74, 65, 80,]
你的输出应该是[1, 2, 1, 0]

思路

首先,我们先来画图分析一下,毕竟图形是最直观的,温度列表数组如下图:

在这里插入图片描述

根据图形,先摒弃任何算法思想,直观的说一下,按照题目的要求,输出结果应该是啥

应该是:【1 天,2 天,1 天,0 天】

怎么算的呢?

其实很好算,但凡跟数组相关的,基本上都要利用数组下标,我们套一下

  • 1 天 = 74温度的下标 1 减去 73 温度的下标 0 = (1 - 0)
  • 2 天 = 80温度的下标 3 减去 74 温度的下标 1 = (3 - 1)
  • 1 天 = 80温度的下标 3 减去 65 温度的下标 2 = (3 - 2)
  • 0 天 = 80 温度是最后一个了,所以为 0

当计算当前温度需要等待的天数时,必须要等到下一轮或者后面好几轮才能得到结果。

比如:

  • 当计算 温度 73 需要等待的天数时,等到第 2 轮循环时,就可以得到了;
  • 当计算 温度 74 需要等待的天数时,等到第 4 轮循环时,才能得到;
  • 当计算 温度 65 需要等待的天数时,等到第 4 轮循环时,才能得到;

可以看到,第 4 轮循环,可以计算出前面温度 65 和温度 74 的结果。

也就是说,需要有一个数据结构来保存当前温度的数组下标,以便后续的计算。

再画图来推导下。

我们初始化一个数组来保存计算的结果,默认都是 0。

【第一轮循环】

在第一轮循环时,数据结构是空的,没有计算,所以只是把温度 73 的下标存入了数据结构中。
在这里插入图片描述

【第二轮循环】

在第二轮循环时,数据结构保存了 0(温度 73 的下标),且本轮的温度 74,大于数据结构中的下标所代表的温度值 73,所以计算 (1 - 0 = 1),将温度 73 的结果赋值为 1,同时将下标 0 删除,下标 1 存入数据结构。

在这里插入图片描述

【第三轮循环】

在第三轮循环时,虽然数据结构不为空(里面有个下标 1),但是本次的温度 65,小于下标 1 所代表的温度 74,所以不参与计算,仅把下标 2 存入数据结构。

在这里插入图片描述

【第四轮循环】

在第四轮循环时,此时数据结构中下标为 2 和 1,本轮是温度 80。

而温度 80 大于下标 2 代表的温度 65,参与计算(3 - 2 = 1),所以温度 65 的结果为 1,删除下标 2;

接着再判断温度 80 大于下标 1 代表的温度 74,参与计算(3 - 1 = 2),所以温度 74 的结果为 2,删除下标 1;

最后将下标 3 存入数据结构。

在这里插入图片描述

【总结】

从上面的推导过程,可以看出来,我们需要一个数据结构来保存温度下标,且按照先进后出的顺序,什么数据结构符合先进后出呢?

而且,只要这个下标参与了计算,就要把它从数据结构中弹出去。

代码实现

 public int[] dailyTemperatures(int[] tmp){
        Stack<Integer> stack = new Stack<>();
        int[] res = new int[tmp.length]; //结果数组
        for (int i = 0; i < tmp.length; i++) { //循环遍历气温
            //如果栈非空,且当前气温tmp[i] 大于 栈顶温度,则将结果存入res
            while (!stack.isEmpty() && tmp[i] > tmp[stack.peek()]){
                Integer pop = stack.pop(); //弹出来的是 气温在数组中的下标
                res[pop] = i - pop; //需要等待的天数为:当前下标-栈顶元素下标
            }
            stack.push(i); //气温入栈,注意存的是气温在数组中的下标
        }
        return res;
}

当然,也可以用暴力解法

public int[] dailyTemperatures2(int[] tmp){
        int[] res = new int[tmp.length];
        for (int i = 0; i < tmp.length; i++) {
            for (int j = i + 1; j < tmp.length; j++) {
                if (tmp[j] > tmp[i]){
                    res[i] = j - i;
                    break;
                }
            }
        }
        return res;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值