(栈应用)每日温度

题目描述

Given a list of daily temperatures T, return a list such that, for each day in the input, tells you how many days you would have to wait until a warmer temperature. If there is no future day for which this is possible, put 0 instead.

For example, given the list of temperatures T = [73, 74, 75, 71, 69, 72, 76, 73], your output should be [1, 1, 4, 2, 1, 1, 0, 0].

Note: The length of temperatures will be in the range [1, 30000]. Each temperature will be an integer in the range [30, 100].

题目分析

题目很明确,以T = [73, 74, 75, 71, 69, 72, 76, 73]为例,T[0]=73,第一个比73大的就是T[1]=74,因此输出数组中的res[0]=1-0=1…拿到这道题目,最容易想到的就是二次遍历数组,找到比当前元素大的第一个值,计算其索引差即可,不过这种算法的时间复杂度较高,为O(N²),应用在这里的话是会超时的。仔细考虑的话,很明显二次遍历的算法是可以优化的,因为很多元素都进行了不必要的遍历,导致了算法的复杂度增大。那么到底是哪里的遍历多余了呢?

还是以原数组T = [73, 74, 75, 71, 69, 72, 76, 73]为例,73和74的计算肯定是没法优化了,因为73,74,75之间构成了递增数列,结果肯定是为1的,那么如果是递减呢?还是来看75,71,69这一递减数列,可以看到,71和69对应的答案都是72,这个时候就会出现多余的遍历了,可能这里看不太明显,比如说给定T=[5,4,3,2,1,6],如果按照二次遍历的算法,那么计算5的时候需要从4遍历到6,计算4的时候需要从3遍历到6…这样一直下去1就被遍历了5次,这显然是多余的,这时候我们就可以想到,如果用6先去和1比,然后得出1的答案,再接着和2比得出2的答案…这样下去每个数就只被遍历一次,极大的提高了效率,那么该用什么样的算法去实现呢?

容易想到,这种算法是先把前面的数给存着,碰到小的数就继续存着,碰到大的数再就近比较,这不就是栈的特点吗?用栈顶的元素和当前元素做比较,如果当前元素偏大,那么栈顶元素对应的结果即是二者索引差;如果栈顶元素偏大,那么就说明是递减的,应该继续往栈里压入当前元素…除此之外还需要考虑一些情况:栈空的情况,如果栈顶元素小于当前元素,那么计算完索引差之后应该做什么呢?…

总结一下,首先为了便于计算索引差,栈存放的就应当是元素的索引值,将当前元素和栈顶元素做比较,如果栈空,那么就直接把当前元素索引放进去;如果栈顶索引对应的元素较大,那么直接压入当前元素索引;如果栈顶索引对于的元素较小,那么当前元素的索引减去栈顶元素的索引得到的结果就是最终结果了,计算结束后就应该将栈顶索引给弹出,继续用当前元素与新的栈顶索引对应元素作比较,比较到最终的结果要么是栈被弹空,要么就是碰到了比当前元素大的索引,不管是哪种情况都应该将当前元素索引压入栈中了,这样就不难写出程序了:

vector<int> dailyTemperatures(vector<int>& T) {
        int size=T.size();
        vector<int>res(size,0);
        stack<int>tmp;
        for(int i=0;i<size;i++)
        {
            if(tmp.empty())tmp.push(i);
            else if(T[tmp.top()]>=T[i])tmp.push(i);
            else 
            {
                while(!tmp.empty()&&T[tmp.top()]<T[i])
                {
                    res[tmp.top()]=i-tmp.top();
                    tmp.pop();
                }
                tmp.push(i);
            }
            
        }   
        return res;
        
    }

可以发现,整个算法实际上只对每个元素遍历了一次,因此算法时间复杂度为O(N),但是却有了O(N)的空间复杂度,与前一种算法时间复杂度为O(N²),空间复杂度为O(1)相比,是明显的用空间换取时间,从而提高了效率。

猜你喜欢

转载自blog.csdn.net/qq_28114615/article/details/84963338