目录
[一、字符串解码(LeetCode 394・中等)](#一、字符串解码(LeetCode 394・中等))
[Java 代码实现(标准栈版)](#Java 代码实现(标准栈版))
[二、每日温度(LeetCode 739・中等)](#二、每日温度(LeetCode 739・中等))
[Java 代码实现(标准单调栈版)](#Java 代码实现(标准单调栈版))
今天我们来拆解两道栈(Stack)的经典中等题:字符串解码和每日温度。这两道题是栈在「嵌套结构处理」和「单调栈」场景下的标杆题目,吃透它们能帮你彻底掌握栈的灵活应用,是算法面试的高频考点。
一、字符串解码(LeetCode 394・中等)
题目描述
给定一个经过编码的字符串,返回它解码后的字符串。编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
示例:
plaintext
输入:s = "3[a]2[bc]"
输出:"aaabcbc"
输入:s = "3[a2[c]]"
输出:"accaccacc"
输入:s = "2[abc]3[cd]ef"
输出:"abcabccdcdcdef"
解题思路
这道题的核心难点是嵌套结构 (比如 3[a2[c]]),栈是处理嵌套结构的天然工具,核心逻辑如下:
- 定义两个栈 :
countStack:存储重复次数kstrStack:存储当前已经解码完成的字符串(用于嵌套场景的回溯)
- 遍历字符串,分 4 种情况处理 :
- 遇到数字 :拼接多位数(比如
10[a]中的10) - 遇到
[:将当前数字压入countStack,当前字符串压入strStack,重置数字和当前字符串 - 遇到
]:弹出countStack的重复次数k,弹出strStack的前缀字符串,将当前字符串重复k次后拼接到前缀后,更新当前字符串 - 遇到字母:直接拼接到当前字符串
- 遇到数字 :拼接多位数(比如
- 遍历结束后,当前字符串即为最终解码结果
Java 代码实现(标准栈版)
java
运行
import java.util.Stack;
public class DecodeString {
public String decodeString(String s) {
Stack<Integer> countStack = new Stack<>();
Stack<StringBuilder> strStack = new Stack<>();
StringBuilder currentStr = new StringBuilder();
int count = 0;
for (char c : s.toCharArray()) {
if (Character.isDigit(c)) {
// 处理多位数,比如 10[a]
count = count * 10 + (c - '0');
} else if (c == '[') {
// 遇到左括号,压入当前计数和当前字符串,重置
countStack.push(count);
strStack.push(currentStr);
currentStr = new StringBuilder();
count = 0;
} else if (c == ']') {
// 遇到右括号,弹出计数,拼接字符串
int repeat = countStack.pop();
StringBuilder prefix = strStack.pop();
// 重复当前字符串 repeat 次,拼接到前缀后
for (int i = 0; i < repeat; i++) {
prefix.append(currentStr);
}
currentStr = prefix;
} else {
// 普通字符,直接拼接
currentStr.append(c);
}
}
return currentStr.toString();
}
}
复杂度分析
- 时间复杂度:O(n),每个字符入栈 / 出栈最多一次,最终字符串长度为 O(n)
- 空间复杂度:O(n),最坏情况(全嵌套)栈的深度为 O(n)
核心知识点总结
- 栈处理嵌套结构:利用栈的「后进先出」特性,完美匹配嵌套括号的「先入后出」逻辑
- 多位数处理 :通过
count = count * 10 + (c - '0')处理连续数字 - 双栈设计:分别存储计数和字符串,实现嵌套场景的回溯与拼接
二、每日温度(LeetCode 739・中等)
题目描述
给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。
示例:
plaintext
输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]
输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]
解题思路
这道题是单调栈的经典入门题,核心目标是「找下一个更大元素」,单调栈能将时间复杂度从 O(n2) 优化到 O(n):
- 维护一个单调递减栈 :栈中存储温度数组的下标,保证栈中下标对应的温度始终递减
- 遍历温度数组 :
- 对于当前温度
temperatures[i],循环判断栈顶下标对应的温度是否小于当前温度 - 若小于:弹出栈顶下标
top,计算天数差i - top,存入结果数组answer[top] - 若大于等于:将当前下标
i压入栈中
- 对于当前温度
- 遍历结束后,栈中剩余下标对应的结果为 0(默认初始化)
Java 代码实现(标准单调栈版)
java
运行
import java.util.Stack;
public class DailyTemperatures {
public int[] dailyTemperatures(int[] temperatures) {
int n = temperatures.length;
int[] answer = new int[n];
// 栈中存储温度数组的下标,维护单调递减
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < n; i++) {
// 当前温度大于栈顶温度,弹出并计算天数差
while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) {
int top = stack.pop();
answer[top] = i - top;
}
// 将当前下标压入栈
stack.push(i);
}
return answer;
}
}
复杂度分析
- 时间复杂度:O(n),每个下标入栈 / 出栈最多一次,总操作次数为 O(n)
- 空间复杂度:O(n),最坏情况(严格递减)栈的大小为 O(n)