1. 程式人生 > >(棧應用)每日溫度

(棧應用)每日溫度

題目描述

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)相比,是明顯的用空間換取時間,從而提高了效率。