一、题目描述
请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。
二、思路分析
暴力解法
看到这个题目后,我首先想到的就是直接暴力解法:
const dailyTemperatures = function(T) {
let len = T.length
for(let i = 0; i < len; i++){
let index = i + 1
while(index < len && T[index] <= T[i]){
index++
}
T[i] = index >= len ? 0 : index - i
}
return T
};
但是写出来代码之后一看,一个数组两层遍历,这暴力解法,时间复杂度直接飙到了O(n^2),这在面试中显然是难以令面试官满意的。
所以得想办法优化优化。
利用栈避免重复操作
其实我们在暴力循环的过程中做了很多重复功。
[73, 74, 75, 71, 69, 72, 76, 73]
拿 75 来说,我们在找比 75 高的第一个温度的过程中,就路过了 71、69、72 、76,其中,72 正是 71 对应的目标温度。
当外层循环走到 71 时,我们才又重复了一遍刚刚走过的路:69 、72。
我们得想办法减少这种重复:利用栈结构可避免重复操作。
尝试去维持一个递减栈:
- 遍历温度,单调递减时将索引入栈;
- 当一个温度将打破这个单调递减趋势(比前一个温度值高)时,将栈顶索引出栈,这两个温度的索引差,就是前一个温度需要等待的天数。
在这个过程中,整个数组只会被遍历一次,期间只进行了一些入栈、出栈操作,因此时间复杂度就是O(n)。
三、AC 代码
/**
* @param {number[]} T
* @return {number[]}
*/
// 入参是温度数组
const dailyTemperatures = function(T) {
const len = T.length // 缓存数组的长度
const stack = [] // 初始化栈
const res = (new Array(len)).fill(0) //初始化结果数组默认值为0
for(let i=0;i<len;i++) {
// 若栈不为空,且温度值将要打破递减趋势
while(stack.length && T[i] > T[stack[stack.length-1]]) {
// 将栈顶温度值对应的索引出栈
const top = stack.pop()
// 当前栈顶温度值与将要打破递减趋势的温度值(第一个高于它的温度值)的索引差值即为等待天数
res[top] = i - top
}
// 入栈温度值索引,方便计算天数
stack.push(i)
}
// 返回结果数组
return res
};
四、总结
- 暴力遍历一定得优化;
- 栈结构可以帮我们避免重复操作;
- 及时地将不必要的数据出栈。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!