题目描述:
给定一个整数数组 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来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/daily-temperatures
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
分析:
自己写出来了,类似于动归,但是实际复杂度貌似还是O(n*n),只能算暴力方法的优化吧。思路是这样,维持一个dp数组,dp[i] 代表,第i个元素后,间隔dp[i]个元素,出现了更大数值。从后往前遍历temperatures数组,最后一个元素的dp记为0,然后每次遍历到temperatures[i] ,都会比较temperatures[i]和temperatures[i+1]的大小,如果temperatures[i]<temperatures[i+1] 则dp[i]=1;否则的话,利用dp[i+1],来寻找比temperatures[i+1]大的数(因为比temperatures[i+1]大的数才有可能比temperatures[i]大),直到dp[i+1]为0或者查找到数组末尾。
该方法存在两层循环遍历,时间复杂度为O(n*n),并不是最好的方法。
代码如下:
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
int n=temperatures.size();
// dp[i]代表temperatures之后有更高温度的间隔天数
vector<int> dp(n,0);
dp[n-1]=0;
for(int i=n-2;i>=0;i--)
{
// 如果后一天温度更高,直接赋值为1
if(temperatures[i]<temperatures[i+1]) dp[i]=1;
// 否则的话利用已经计算出的dp,来推断出间隔天数
else
{
int index=i+1;
dp[i]=0;
// index可能为更大的元素,或者查找到数组末尾结束
while(dp[index]!=0&&index<=n)
{
index=index+dp[index];
if(temperatures[index]>temperatures[i])
{
dp[i]=index-i;
break;
}
}
}
}
return dp;
}
};
估计是有O(n)的做法的,去看了看题解,果然,单调栈的做法是可以达到O(n)的。我思来想去,也没想出来怎么用单调栈做,因为我一直默认单调栈中存放的是从小到大的元素,然而,栈s维持一个单调队列,保存的是temperatures的下表,从栈底到栈顶,元素依次递减。
明确这一点就好办了,遍历 temperatures,如果temperatures[i] <temperatures[s.top()],那么,当前元素的下标 i 入栈,否则的话,temperatures[i]就是比temperatures[s.top()]大的下一个元素,令res[s.top()]=i - s.top(),弹出栈顶元素。比较下一个栈顶元素,直到栈为空,或者temperatures[i] <temperatures[s.top()]。
这种方法的时间复杂度为O(n),而且容易记。
详细题解如下:
https://leetcode-cn.com/problems/daily-temperatures/solution/mei-ri-wen-du-by-leetcode-solution/力扣
代码如下:
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
// 栈s维持一个单调队列,保存的是temperatures的下表,从栈底到栈顶,元素依次递减
stack<int> s;
int n=temperatures.size();
// res为最终返回的数组
vector<int> res(n);
// 遍历temperatures
for(int i=0;i<n;i++)
{
// 栈不为空
if(!s.empty())
{
int top=s.top();
// 判断当前元素和栈顶元素大小 (带入下标在temperatures中计算,以下均是这种方式)
// 如果当前元素大,那么说明当前元素正是比栈顶元素大的下一个元素,更新栈顶元素的res,并且弹出栈顶元素
// 计算下一个栈顶元素和当前元素的大小,重复以上操作,直至栈为空,或者当前元素比栈顶元素小
while(s.empty()==false&&temperatures[s.top()]<temperatures[i])
{
res[s.top()]=i-s.top();
s.pop();
}
}
// 最后在栈中加上当前元素
s.push(i);
}
return res;
}
};