算法-棧-每日溫度

算法-棧-每日溫度

1 題目概述

1.1 題目出處

https://leetcode-cn.com/problems/daily-temperatures/

1.2 題目描述

根據每日 氣溫 列表,請重新生成一個列表,對應位置的輸出是需要再等待多久溫度纔會升高超過該日的天數。如果之後都不會升高,請在該位置用 0 來代替。

例如,給定一個列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的輸出應該是 [1, 1, 4, 2, 1, 1, 0, 0]。

提示:氣溫 列表長度的範圍是 [1, 30000]。每個氣溫的值的均爲華氏度,都是在 [30, 100] 範圍內的整數。

2 循環遍歷

2.1 思路

最直觀的,遍歷所有元素,每次一次往後檢查直到第一個比當前元素氣溫高的即求得氣溫升高所有天數。

2.2 代碼

class Solution {
    public int[] dailyTemperatures(int[] T) {
        int[] result = new int[T.length];
        for(int i = 0; i < T.length; i++){
            for(int j = i + 1; j < T.length; j++) {
                if(T[j] > T[i]){
                    result[i] = j-i;
                    break;
                }
            }       
        }
        return result;
    }
}

2.3 時間複雜度

在這裏插入圖片描述
O(N^2)

2.4 空間複雜度

O(1)

3 棧

3.1 思路

利用棧,如果棧爲空或者當前元素比棧頂元素大,就將棧頂元素出棧並計算相應結果,然後繼續比較下一個棧頂元素,直到當前元素不大於棧頂元素或棧爲空。

最後將元素直接放入棧頂。

遍歷完成後,還需要處理棧中元素,剩餘的元素代表右側沒有比他們更高的氣溫了,所以升高氣溫天數都爲0。

3.2 代碼

class Solution {
    public int[] dailyTemperatures(int[] T) {
        int[] result = new int[T.length];
        // 該int數字0位表示在原氣溫數組中位置,1位表示氣溫值
        Stack<int[]> tmp = new Stack<>();
        int[] top;
        for(int i = 0; i < T.length; i++){
            if(tmp.isEmpty()){
                tmp.add(new int[]{i, T[i]});
            }else{
                while(!tmp.isEmpty()){
                    top = tmp.peek();
                    if(T[i] <= top[1]){
                        break;
                    }
                    // 當前數字大於棧頂就出棧
                    tmp.pop();
                    // 升高所需天數
                    result[top[0]] = i - top[0];
                    
                }
                // 最後將當前數字入棧
                tmp.add(new int[]{i, T[i]});
            }
        }
        return result;
    }
}

3.3 時間複雜度

在這裏插入圖片描述
O(N)

3.4 空間複雜度

O(N)

4 數組模擬棧

4.1 思路

思路和前面棧方法相同,只不過不用Stack類而是自己用數組模擬棧,減少了很多不必要的複雜操作開銷。

4.2 代碼

class Solution {
    public int[] dailyTemperatures(int[] T) {
        int[] result = new int[T.length];
        // 該int數字0位表示在原氣溫數組中位置,1位表示氣溫值
        int[][] tmp = new int[T.length][2];
        int[] top;
        // 標記tmp中當前應處理的行下標
        int offset = -1;
        for(int i = 0; i < T.length; i++){
            while(offset > -1){
                top = tmp[offset];
                if(T[i] <= top[1]){
                    break;
                }
                offset--;
                // 升高所需天數
                result[top[0]] = i - top[0];  
            }
            // 最後將當前數字入棧
            tmp[++offset] = new int[]{i, T[i]};
        }
        return result;
    }
}

4.3 時間複雜度

在這裏插入圖片描述
O(N)

4.4 空間複雜度

O(N)

5 倒序查找

5.1 思路

要求右側第一個溫度跟高的元素,所以其實從右往左找更方便。

而且,我們還加入一個快速判定方法,這裏假設初始時j=i+1:

  • T[i] < T[j]
    顯然result[i] = j - I;
  • T[i] >= T[j]且result[j] == 0,即i元素溫度不低於j元素,但j元素右側沒有更高的溫度,則i元素顯然也不能在右側升高溫度:
    result[i] = 0;
  • T[i] >= T[j]且result[j] > 0,即i元素溫度不低於j元素,且j元素右側有更高的溫度,此時可通過j = result[j] + j快速找到第一個比j高的溫度的下標,然後讓i和這個新下表元素比較

5.2 代碼

class Solution {
    public int[] dailyTemperatures(int[] T) {
        int[] result = new int[T.length];
        result[T.length - 2] = 0;
        for(int i = T.length - 2; i >= 0; i--){
            int j = i + 1;
            // 往右找第一個比i還大的
            while(true){
                if(T[i] < T[j]){
                    result[i] = j - i;
                    break;
                }else if(result[j] == 0){
                    // 注意此時T[i] >= T[j]
                    result[i] = 0;
                    break;
                } else{
                    // 注意此時T[i] >= T[j]且result[j] > 0
                    // 找到第一個比j高的溫度的下標
                    j = result[j] + j;
                }
            }
        }
        return result;
    }
}

5.3 時間複雜度

在這裏插入圖片描述
O(N)

5.4 空間複雜度

O(1)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章