思路:从后往前遍历数组。
原数组用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个数一个一个往后找的,也就是如果测试用例找这样子:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
75 | 66 | 64 | 63 | 69 | 74 | 72 | 76 |
3 | 2 | 1 | 1 | 2 | 1 | 0 |
假设现在我们已经计算出了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%之间。