【算法】单调栈小结

117 阅读1分钟

一、前言

单调栈: 实际上也是栈,只是限制多了些,栈内元素是有序的。

单调栈可分为两种: 按照出栈的顺序决定,出栈顺序递减就是递减栈,出栈顺序递增就是递增栈。

  • 单调递增栈: 只有比栈顶元素小的数才能入栈,否则需把栈顶先出栈。
  • 单调递减栈: 只有比栈顶元素大的数才能入栈,否则需把栈顶先出栈。
# 单调递增栈:
# 栈内顺序:[3, 6, 10],出栈顺序为:[10, 6, 3]

# 单调递减栈:
# 栈内顺序:[10, 6, 3],出栈顺序为:[3, 6, 10]

总结下算法模板:

Stack<Integer> st = new Stack<>();
for (int r = 0; r <= n; ++r) {
    // 比较栈顶元素
    while (!st.empty() && h < heights[st.peek()]) {
        // 出栈操作
    }
    st.push(r);
}

题目:

题目名难易程度思路
496. 下一个更大元素 I简单
739. 每日温度中等
316. 去除重复字母中等
901. 股票价格跨度中等
402. 移掉 K 位数字中等
581. 最短无序连续子数组中等
84. 柱状图中最大的矩形困难
42. 接雨水困难

希望学习完这篇文章的你,再遇到这类型时,不再 “纯纯的”,而是觉得这题 “纯纯的”。



二、题目

(1)每日温度

739. 每日温度

题干分析

这个题目说的是,给你一个不为空的整数数组,数组中的元素表示每天的温度。你要计算出,对于每一天来说,温度升高需要等待的天数。如果对于某一天,未来不存在比它更高的温度,就把它对应的等待天数设置为 0。

比如说,给你的温度数组是:

1, 3, 1, 3, 2, 6

对于每一天来说,温度升高需要等待的天数是:

1, 4, 1, 2, 1, 0

思路解法

public class AlgoCasts {

    // Time: O(n^2), Space: O(1)
    public int[] dailyTemperaturesBruteForce(int[] T) {
        int n = T.length;
        int[] result = new int[n];
        for (int i = 0; i < n; ++i) {
            int j = i + 1;
            while (j < n && T[j] <= T[i]) ++j;
            if (j < n) result[i] = j - i;
            // else result[i] = 0;
        }
        return result;
    }

    // Time: O(n), Space: O(n)
    public int[] dailyTemperaturesStack(int[] T) {
        int n = T.length;
        int[] result = new int[n];
        Stack<Integer> st = new Stack<>();
        for (int i = 0; i < n; ++i) {
            while (!st.empty() && T[st.peek()] < T[i]) {
                int idx = st.pop();
                result[idx] = i - idx;
            }
            st.push(i);
        }
        // while (!st.empty()) result[st.pop()] = 0;
        return result;
    }

    // Time: O(n), Space: O(1)
    public int[] dailyTemperaturesSkip(int[] T) {
        int n = T.length;
        int[] result = new int[n];
        for (int i = n-2; i >= 0; --i) {
            int j = i + 1;
            while (T[j] <= T[i] && result[j] != 0) j += result[j];
            if (T[j] > T[i]) result[i] = j - i;
            // else result[i] = 0;
        }
        return result;
    }

}