題目
根據每日 氣溫
列表,請重新生成一個列表,對應位置的輸出是需要再等待多久溫度纔會升高超過該日的天數。如果之後都不會升高,請在該位置用 0
來代替。
例如,給定一個列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
,你的輸出應該是 [1, 1, 4, 2, 1, 1, 0, 0]
。
提示:氣溫
列表長度的範圍是 [1, 30000]
。每個氣溫的值的均爲華氏度,都是在 [30, 100]
範圍內的整數。
解題思路
解法一:暴力法
從當前位置的下一個位置開始遍歷數組,如果找到一個比當前元素大的值,就計算相差的天數;或者直到遍歷完整個數組也沒找到,那麼相差的天數賦值爲0,java中數組初始化時就是0,所以這步可以省略不寫。
複雜度分析:
時間複雜度:O(n^2),對於數組中的每個元素,最壞情況下需要遍歷其之後的每個元素,對於第 k 個元素,需要遍歷之後的 n-k 個元素。總共需要 (n-1)+(n-2)+…+(n-k)…+(n-n) = n^2 -(1+2+…+n) = (n^2-n)/2 個元素,所以漸進時間複雜度爲 O(n^2)。
空間複雜度:O(1),沒有用到額外變量。
解法二:單調棧
維護一個存儲下標的單調棧,從棧底到棧頂的下標對應的溫度列表中的溫度依次遞減。如果一個下標在單調棧裏,則表示尚未找到下一次溫度更高的下標。
正向遍歷溫度列表。對於溫度列表中的每個元素 T[i]:
1)如果棧爲空,則直接將 i 進棧。
2)如果棧不爲空,則比較棧頂元素 popId 對應的溫度 T[popId] 和當前溫度 T[i],如果 T[i] > T[popId],則將 popId 彈出,並將 popId 對應的等待天數賦爲 i - popId。
3)重複上述操作直到棧爲空或者棧頂元素對應的溫度大於等於當前溫度,然後將 i 進棧。
複雜度分析:
時間複雜度:O(n),其中 n 是溫度列表的長度。正向遍歷溫度列表一遍,對於溫度列表中的每個下標,最多有一次進棧和出棧的操作。
空間複雜度:O(n),其中 n 是溫度列表的長度。需要維護一個單調棧存儲溫度列表中的下標。
代碼
解法一:暴力法
class Solution {
public int[] dailyTemperatures(int[] T) {
int n = T.length;
int[] res = new int[n];
for(int i=0; i<n; i++){
for(int j=i+1; j<n; j++){
if(T[j]>T[i]){
res[i] = j-i;
break;
}
}
}
return res;
}
}
解法二:單調棧
class Solution {
public int[] dailyTemperatures(int[] T) {
int n = T.length;
int[] res = new int[n];
Deque<Integer> stack = new ArrayDeque<Integer>();
for(int i=0; i<n; i++){
// 棧頂元素小於當前元素,說明找到了一個目標值,那麼就出棧
while(!stack.isEmpty() && T[stack.peekLast()] < T[i]){
int id = stack.removeLast();
res[id] = i-id;
}
// 如果棧爲空,或者棧頂元素大於等於當前元素(滿足單調遞減關係),就將當前元素入棧
stack.addLast(i);
}
return res;
}
}