題目描述
根據每日 氣溫 列表,請重新生成一個列表,對應位置的輸入是你需要再等待多久溫度纔會升高超過該日的天數。如果之後都不會升高,請在該位置用 0 來代替。
例如,給定一個列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的輸出應該是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示:氣溫 列表長度的範圍是 [1, 30000]。每個氣溫的值的均爲華氏度,都是在 [30, 100] 範圍內的整數。
解題思路
這個題目可以看做是從左往右找第一個比這個數大(或者小)的數的位置,然後求出下標只差就可以了。說是很容易,但是如果做的話,最暴力的方法:我們求第i位置的時候,從該位置開始找到右邊第一個比這個數大的數的位置時結束本次遍歷。一次類推,這樣下來的時間複雜度是O(n^2).這種簡單暴力的方法應該都能夠想出來。用單調棧的方法能夠以O(n)的時間複雜度完成本次操作:
我們設置一個棧,其中要求這個棧從棧底到棧頂是單調遞減的。我們在入棧的時候不進行任何操作,當不滿足單調棧的從棧底到棧頂由大變小的規則時,我們就需要將棧頂元素彈出,在彈出時我們才進行相關操作,也就是說,只有棧需要彈出時才能激發操作。這個操作就是“終於遇到了比棧頂元素大的右邊第一個數了”,這時候我們就記錄這個位置比棧頂元素所在的位置大多少(下標差),只要一直不滿足這個單調棧的規定,就一直彈出,一直記錄結果,最後遍歷完畢整個數組,剩下的棧內元素都是那些右邊不存在比該位置更大的數了,所以直接填寫0即可。
整個過程可以按照以下的僞代碼執行:
對於T[i]: i:0~(length-1){
if(stack爲空 || T[i]<=棧頂元素){
將T[i]壓入棧;
continue;
}
while(棧不爲空&&T[i]大於棧頂元素的值){
result【棧頂元素的下標】 = i(當前元素的下標) - 棧頂元素的下標;
彈出棧頂元素;
}
while(棧頂元素非空){
result[棧頂元素下標] = 0;
彈出棧頂元素。
}
}
下面是代碼:Leetcode-739 每日溫度(git)Leetcode-739
vector<int> dailyTemperatures(vector<int>& T) {
stack<pair<int,int>> st;
int size = T.size();
vector<int> res(size,0);
if(size<=1) return res;
for(int i=0;i<T.size();i++){
if(st.empty() || T[i]<=st.top().first){
st.push(make_pair(T[i],i));
continue;
}
while(!st.empty()&&T[i]>st.top().first){ //遇到比棧的頭結點大的就全部進行彈出,只有在彈出數據的時候往結果數據集合填充數據。
res[st.top().second] = i - st.top().second;
st.pop();
}
st.push(make_pair(T[i],i));
}
while(!st.empty()){
res[st.top().second]=0;
st.pop();
}
return res;
}