单调栈真的懂了呀系列《每日温度》

80 阅读2分钟

价值:记录学习过程的思考,本身就是一场动态规划的前生,记忆化搜索。

单调栈:及时去掉无用数据,保证栈中数据有序。

Problem: LCR 038. 每日温度

思路

"数组""当前元素下一个 最大 ""当前元素下一个 最小"

暴力怎么做?
正向:从当前这个元素,往后枚举,找到大于当前的,得出结果,然后后移一位,每个结果的计算过程
是N,枚举N个,时间复杂度是 N*N

反向:从当前这个元素,往前枚举,找到 < 当前的"第一个",得出结果,但是要不要出栈呢,是不是无用数据?
不是,很有可能比如 213 这种情况,对于 2来说,当前栈顶不是无效的,1反而是无效的,因为1得到了结果,及时移走。
每次都从这个末尾算,直到有一个比他大的,说明他不是 从右到左,第一个最大的这个定义,这个时候才位置移动。 时间复杂度 N*N


[1,4,3,5,5,2,3,6]

正向枚举,
先放进去一个,对后边的枚举、判断
判断                当前元素 > 栈顶元素
如果无法得到结果,就入栈,否则得到结果后,就变成了无用数据,及时出栈
[1]
[4]
[4,3]
[5]
[5,5]
[5,5,2]
[5,5,3]
[6]

反向枚举,"栈不空"
先放进去一个,对后边的枚举、判断
判断                当前元素 < 栈顶元素  统统入栈,直到出现 当前元素大于栈顶,出栈
[6]
[6,3]
[6,3,2]
[6,5]
[6,5前]
[6,5,3]
[6,5,4]
[6,5,4,1]

Code

class Solution {
    //L->R
    // public int[] dailyTemperatures(int[] temperatures) {
    //     int n = temperatures.length;

    //     Deque<Integer> stack = new ArrayDeque<>();

    //     int [] ans = new int[n];

    //     for(int i = 0 ; i < n; i++){

    //         //对于每一个元素i来说,先入栈,找到结果就没用了,及时清除,否则入栈
    //         //这里用值显示下 入 :73 ,74>73?pop->ans : append 74 这个过程
    //         while(!stack.isEmpty() && temperatures[i] > temperatures[stack.peekLast()]){
    //             int top_index = stack.pollLast();
    //             ans[top_index] = i - top_index;
    //         }
    //         stack.addLast(i);
    //     }
    //     return ans;
    // }


    // i  : 0           1                     2                     3.          4.                 5

    // 栈 : 0  (74>73)--i~0走--nil--i~1  (75>74)--i~1走--nil--i~2. (71<75)--i~3. (69<71)--i~4  (72>71)--i~4走

    // res: 1-0.                    2-1                                         5-4

    //R->L。单调小
    public int[] dailyTemperatures(int[] temperatures) {
        int n = temperatures.length;

        Deque<Integer> stack = new ArrayDeque<>();

        int [] ans = new int[n];

        for(int i = n-1; i>=0; i--){
            int curValue = temperatures[i];

            while(!stack.isEmpty() && temperatures[stack.peekLast()] <= curValue){
                //R->L枚举过程,不会再作为找答案有效判断,栈顶数据不会再用到了
                stack.pollLast();
            }

            if(!stack.isEmpty()){
                ans[i] = stack.peekLast() - i;
            }

            stack.addLast(i);
        }

        return ans;
    }

}