hot100 栈专题

1 有效的括号

不难,但是要考虑多种情况

技巧:入栈的时候,( 就入 ),[ 就入 ]。

如果遇到右括号,则判断stack是否为空,考虑())的情况

再考虑当前字符c != stack.peek()的情况,也就是(( ] )的情况。

上面这两种情况直接返回fals就行。

第三种情况就是正常匹配,当前字符是)且栈顶是(,那么直接stack.pop()就行。

最后结束for循环,返回stack.isEmpty();

如果不为空,说明左括号有剩余,[ [ [ ]的情况就是,直接返回false;栈空则说明是有效的括号,返回true;

java 复制代码
class Solution {
    public boolean isValid(String s) {
        Deque<Character> stack = new LinkedList<>();
        int len = s.length();
        for (int i = 0; i < len; i++) {
            if (s.charAt(i) == '(') {
                stack.push(')');
            } else if (s.charAt(i) == '[') {
                stack.push(']');
            } else if (s.charAt(i) == '{') {
                stack.push('}');
            } else if (stack.size() == 0 || s.charAt(i) != stack.peek()) {
                return false;
            } else {
                stack.pop();
            }
        }
        return stack.isEmpty();
    }
}

2 最小栈

核心思路:辅助栈法(最优解)

主栈:存储所有入栈的元素,实现普通栈的基本操作;

辅助栈:同步存储「当前主栈中的最小值」,保证辅助栈的栈顶始终是主栈当前的最小值。

push:主栈入栈元素,辅助栈入栈「当前元素与辅助栈顶的较小值」;

pop:主栈和辅助栈同时出栈(保证两者长度一致);

getMin:直接返回辅助栈的栈顶元素。

java 复制代码
class MinStack {
    private Deque<Integer> mainStack;
    private Deque<Integer> minStack;
    public MinStack() {
        mainStack = new LinkedList<>();
        minStack = new LinkedList<>();
        minStack.push(Integer.MAX_VALUE);
    }
    
    public void push(int val) {
        mainStack.push(val);
        int curMin = Math.min(val, minStack.peek());
        minStack.push(curMin);
    }
    
    public void pop() {
        mainStack.pop();
        minStack.pop();
    }
    
    public int top() {
        return mainStack.peek();
    }
    
    public int getMin() {
        return minStack.peek();
    }
}

3 字符串解码

数字栈:存储待处理的重复次数 k(处理多位数,如 12[abc] 中的 12);

字符串栈:存储待拼接的前缀字符串(处理嵌套时的外层字符串,如 3[a2[b]] 中 2[b] 外层的 a);

遍历逻辑:

遇到数字:累积计算多位数(如 12 = 1*10 + 2);

遇到 [:将当前累积的数字压入数字栈,当前拼接的字符串压入字符串栈,然后重置数字和字符串;

遇到 ]:弹出数字栈的重复次数 k,弹出字符串栈的前缀字符串,将当前字符串重复 k 次后拼接到前缀后;

遇到字母:直接拼接到当前字符串。

java 复制代码
import java.util.Deque;
import java.util.LinkedList;

class Solution {
    public String decodeString(String s) {
        // 数字栈:存储待执行的重复次数(处理嵌套结构时的"重复指令")
        Deque<Integer> numStack = new LinkedList<>();
        // 字符串栈:存储括号外层的前缀字符串(处理嵌套时的"外层存档")
        Deque<String> strStack = new LinkedList<>();
        // 当前正在拼接的临时字符串(括号内待重复的内容)
        StringBuilder curStr = new StringBuilder();
        // 当前累积的数字(处理多位数,如"12[a]"中的12需要逐步计算)
        int curNum = 0;
        // 将字符串转为字符数组,方便逐个遍历
        char[] sArr = s.toCharArray();
        
        // 遍历每个字符,逐字符处理解码逻辑
        for (char c : sArr) {
            // 情况1:当前字符是数字 → 累积计算多位数
            if (Character.isDigit(c)) {
                // 例如:curNum=1,遇到'2' → 1*10 + 2 = 12
                curNum = curNum * 10 + (c - '0');
            } 
            // 情况2:当前字符是左括号'[' → 存档当前状态,准备处理括号内内容
            else if (c == '[') {
                // 1. 把当前累积的重复次数压入数字栈(存档)
                numStack.push(curNum);
                // 2. 把当前拼接的字符串压入字符串栈(存档外层前缀)
                strStack.push(curStr.toString());
                // 3. 重置临时数字,准备处理括号内的新数字
                curNum = 0;
                // 4. 重置临时字符串,准备拼接括号内的内容
                curStr = new StringBuilder();
            } 
            // 情况3:当前字符是右括号']' → 拼接重复后的字符串
            else if (c == ']') {
                // 1. 弹出数字栈顶的重复次数(本次要重复的次数)
                int loop = numStack.pop();
                // 2. 弹出字符串栈顶的前缀(括号外的内容)
                String prefix = strStack.pop();
                // 3. 新建临时字符串,先拼接外层前缀
                StringBuilder temp = new StringBuilder(prefix);
                // 4. 把当前括号内的字符串重复指定次数,拼接到前缀后
                for (int i = 0; i < loop; i++) {
                    temp.append(curStr.toString());
                }
                // 5. 更新临时字符串为拼接后的结果,继续处理外层逻辑
                curStr = temp;
            } 
            // 情况4:当前字符是字母 → 直接拼接到临时字符串
            else {
                curStr.append(c);
            }
        }
        // 遍历结束,返回最终拼接完成的解码字符串
        return curStr.toString();
    }
}

4 每日温度

单调递减栈

先把下标0push入栈

然后从1开始,如果温度比栈顶下标的温度低,那就入栈。

如果下标i对应的温度比栈顶下标的温度高,那么就进入while循环,!st.isEmpty()&&t[i] >t[st.peek()]

然后给res[st.peek()]赋值为i-st.peek()

st.pop()

最后退出while循环,把i push进去

java 复制代码
class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        Deque<Integer> st = new LinkedList<>();
        st.push(0);
        int len = temperatures.length;
        int[] res = new int[len];
        for (int i = 1; i < len; i++) {
            if (temperatures[i] <= temperatures[st.peek()]) {
                st.push(i);
            } else {
                while (!st.isEmpty() && temperatures[i] > temperatures[st.peek()]) {
                    res[st.peek()] = i - st.peek();
                    st.pop();
                }
                st.push(i);
            }
        }
        return res;
    }
}

5 柱状图中最大的矩形

单调递增栈

遇到h[i] < h[st.peek()]的就while()出栈

height = h[st.pop()]

width = i - st.peek() - 1;

更新area

加左右哨兵,同意边界处理,让第一个能入栈,最后一个能弹出。

java 复制代码
class Solution {
    public int largestRectangleArea(int[] heights) {
        int len = heights.length;
        if (len == 1) return heights[0];
        int[] newHeights = new int[len + 2];
        for (int i = 0; i < len; i++) {
            newHeights[i + 1] = heights[i];
        }
        newHeights[0] = 0;
        Deque<Integer> st = new LinkedList<>();
        int res = 0;
        for (int i = 0; i < newHeights.length; i++) {
            while (!st.isEmpty() && newHeights[i] < newHeights[st.peek()]) {
                int curIndex = st.pop();
                int curHeight = newHeights[curIndex];
                int width = i - st.peek() - 1;
                res = Math.max(res, width * curHeight);
            }
            st.push(i);
        }
        return res;
    }
}
相关推荐
2401_879503411 小时前
C++中的观察者模式变体
开发语言·c++·算法
阿贵---2 小时前
C++中的备忘录模式
开发语言·c++·算法
setmoon2142 小时前
C++中的观察者模式实战
开发语言·c++·算法
2403_835568472 小时前
C++代码规范化工具
开发语言·c++·算法
tankeven2 小时前
HJ138 在树上游玩
c++·算法
lihihi3 小时前
P1209 [USACO1.3] 修理牛棚 Barn Repair
算法
weixin_387534223 小时前
Ownership - Rust Hardcore Head to Toe
开发语言·后端·算法·rust
庞轩px3 小时前
MinorGC的完整流程与复制算法深度解析
java·jvm·算法·性能优化
Queenie_Charlie3 小时前
Manacher算法
c++·算法·manacher