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

来源:力扣(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;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值