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(处理多位数,如 12abc 中的 12);

字符串栈:存储待拼接的前缀字符串(处理嵌套时的外层字符串,如 3a2\[b] 中 2b 外层的 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()&&ti >tst.peek()

然后给resst.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 柱状图中最大的矩形

单调递增栈

遇到hi < hst.peek()的就while()出栈

height = hst.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;
    }
}
相关推荐
ZhengEnCi2 小时前
Agent 架构怎么选:从单 Agent 到多 Agent 编排的选型决策指南
算法·架构
秋天的怀念_David3 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Pniubi3 小时前
力扣283移动零(双指针法)
算法·leetcode·职场和发展
hhb_6183 小时前
大模型落地三重优化实战
人工智能·算法·机器学习
云和数据.ChenGuang4 小时前
光哥说Python RAG 系统需要哪些评估指标:从检索到生成的全链路评测指南
网络·人工智能·python·算法·langchain
2601_970703835 小时前
工业除湿机租赁:把一份租金合同拆开看
大数据·数据结构·算法·数据库架构·推荐算法
心中有你02145 小时前
Java实现Dijkstra最短路径算法(邻接表 + 优先队列)
java·数据库·算法
ZhengEnCi6 小时前
同样的模型,为什么本地和云 API 差别那么大:量化精度、聊天模板与采样参数的三大元凶
人工智能·算法·llm
Flynn Liang6 小时前
RAG 答非所问/幻觉怎么破?Spring AI QuestionAnswerAdvisor 召回优化实战(TopK/重排/混合检索)
人工智能·算法·spring·rag·幻觉·springai
liminla!7 小时前
SQL 从入门到进阶:语法速查与实战练习(完整优化版)
数据库·sql·算法