LeetCode Daily Temperatures

思路:从后往前遍历数组。

原数组用T表示。设置一个可变数组ans保存结果,用于保存每一天为了等到一个比这天更暖和的天(即找到一个比这个数更大的数)应该等待的天数。数组下标从0到n-1,n表示数组中总的元素个数。对于数组中的最后一个数,毫无疑问,ans[n-1]=0;对于剩下的每一个数则有几种情况。

第一种情况是最简单的,就是对于数组中的第i个数而言,位于其后的第i+1个大于它即T[i]<T[i+1];这时候ans[i]=1;

第二种情况是,T[i] >= T[i+1]并且ans[i+1]=0,即第i个数小于等于第i+1数,但是数组中i+2到n-1的位置上不存在比第i+1个数更大的数了。T[i]>T[i+1],并且T[i+1]是T[i]以后最大的数,因此,T[i]是从位置i到位置n-1中最大的数。也就是ans[i]=0;

第三种情况就是, T[i] > T[i+1] 但是ans[i+1] > 0,即T[i+1]后面还存在比T[i+1]更大的数,但是无法确定是否存在比T[i]更大的数了,这时候没办法了,只能从T[i+1]一直找到T[n-1],看看有没有数比T[i]大了。

AC代码一

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& T) {
        vector<int> ans(T.size(), 0);
        for(int i=T.size()-2;i>=0;i--){
            if(T[i+1]<=T[i]){
                if(ans[i+1]==0){
                    ans[i] = 0;
                }else{
                    int j = i+1;
                    while(j<T.size()&& T[j]<=T[i]){
                        j++;
                    }
                    if(j==T.size()){
                        ans[i] = 0;
                    }else{
                        ans[i] = j - i;
                    }
                }
            }else{
                ans[i] = 1;
            }
        }
        return ans;
    }
};

此代码的用时为840ms,只超过了16%的人。因此,这段代码还存在一定的优化空间。

可是耗时最大的地方一个是外层的for,另一个是里层的while循环,for循环是无法优化了,毕竟对每个数都需要产生一个结果,那么能优化的就只剩下里层的while循环了。那么怎么优化while循环呢?思考了一下,我发现现在的代码是从第i+1个数一个一个往后找的,也就是如果测试用例找这样子:

01234567
7566646369747276
 3211210

假设现在我们已经计算出了66-76这个区间内每一个元素的ans,如上图所示。

那么当我们要计算ans[0]时,我们首先比较T[0]与T[1],发现T[0]>T[1],但是ans[1]不等于0,那么接下来,根据上述代码,我们一次比较T[0]与T[1],T[2],....,T[4],....T[7]。这种比较一直要持续到以下几种情况结束:位置j超出了有效范围;T[j]>T[i];而在这个问题不仅没有考虑到可能会遇到T[j]<=T[i]且ans[j]=0的情况,同时也没有考虑到不需要和比T[i+1]还小的数进行比较的情况。那么该怎么规避以上几种情况呢?我想到的解决办法是这样的:

当T[i+1]<T[i]时,从T[i+1]到T[n-1]这些数中只选取比T[i+1]大的数和T[i]比较。那么怎么选取比T[i+1]大的数呢?答案是利用已经计算出来的ans[i+1],...ans[n-1]。我们选取下标j=i+1+ans[i+1],将T[j]和Ti]比较,若T[j]大于T[i],则找到了比T[i]大的数;若T[j]<=T[i],ans[j]=0,则出现了第二种情况,说明我们不可能找到比T[i]大的数了,令ans[i]=0;否则ans[j]>0,则又出现了第三种情况,只是这次的规模变小了一点,变成了从T[j]到T[n-1]中找第一个比T[i]大的数,则j = j + ans[j+1]。

这样就写出了优化后的代码如下:

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& T) {
        if(T.empty()){
            return {};
        }
        vector<int> ans(T.size(), 0);
        for(int i=T.size()-2;i>=0;i--){
            if(T[i+1]<=T[i]){
                if(ans[i+1]==0){
                    ans[i] = 0;
                }else{
                    int j = i + 1 + ans[i+1];
                    while(j<T.size()&& T[j]<=T[i]){
                        if(ans[j]>0){
                            j = j + ans[j];                            
                        }else{
                            break;
                        }
                    }
                    if(j==T.size() || T[j]<=T[i]){
                        ans[i] = 0;
                    }else{
                        ans[i] = j - i;
                    }
                }
            }else{
                ans[i] = 1;
            }
        }
        return ans;
    }
};

这次的运行时间在60%-90%之间。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值