哪吒教你用栈搞定括号匹配和每日温度问题:从入门到入土
大家好,我是哪吒,今天咱们来聊聊两个经典的算法问题:有效的括号和每日温度。这两个问题看似简单,但背后隐藏的栈思想却非常巧妙。我会用幽默搞笑的方式,带你一步步理解它们的实现思路,顺便教你用 Java 和 C++ 写出优雅的代码。
1. 有效的括号:哪吒的“括号大冒险”
问题描述
给定一个只包含 '('
、')'
、'{'
、'}'
、'['
、']'
的字符串,判断它是否有效。有效字符串需要满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
哪吒的思路
想象一下,你是一个括号管理员,手里拿着一堆括号卡片。每次遇到一个左括号(比如 (
、{
、[
),你就把它对应的右括号(比如 )
、}
、]
)放进一个“魔法栈”里。当你遇到一个右括号时,就从栈顶取出一个卡片,看看是否匹配。
- 如果匹配,继续;
- 如果不匹配,或者栈空了,说明这个字符串无效。
最后,如果栈空了,说明所有括号都匹配成功,字符串有效;否则,无效。
代码实现
Java 版本
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
char[] chars = s.toCharArray();
for (char c : chars) {
switch (c) {
case '(':
stack.push(')');
break;
case '{':
stack.push('}');
break;
case '[':
stack.push(']');
break;
default:
if (stack.isEmpty() || !stack.pop().equals(c)) {
return false;
}
}
}
return stack.isEmpty();
}
C++ 版本
bool isValid(string s) {
stack<char> stack;
for (int i = 0; i < s.size(); i++) {
switch (s[i]) {
case '(':
stack.push(')');
break;
case '{':
stack.push('}');
break;
case '[':
stack.push(']');
break;
default:
if (stack.empty()) {
return false;
}
char c = stack.top();
stack.pop();
if (c != s[i]) {
return false;
}
}
}
return stack.empty();
}
递归方式:哪吒的“套娃大法”
如果你觉得栈还不够酷,可以试试递归。递归的核心思想是:
- 每次遇到左括号,递归处理后面的字符串。
- 遇到右括号时,检查是否与当前左括号匹配。
- 如果匹配,继续递归;否则,返回失败。
不过,递归的实现会比栈复杂一些,而且容易栈溢出(毕竟递归深度和字符串长度成正比)。所以,栈是更优雅的选择。
2. 每日温度:哪吒的“温度追踪器”
问题描述
给定一个整数数组 temperatures
,表示每天的温度,返回一个数组 answer
,其中 answer[i]
是指对于第 i
天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0
来代替。
哪吒的思路
这个问题可以用单调栈来解决。单调栈的核心思想是:
-
维护一个栈,栈里存放的是“还没有找到更高温度的日期索引”。
-
遍历温度数组,对于每一天的温度:
- 如果当前温度比栈顶的温度高,说明栈顶的那一天找到了更高温度,计算天数差,并更新结果数组。
- 重复上述过程,直到栈为空或当前温度不大于栈顶温度。
-
最后,将当前日期的索引压入栈中。
代码实现
Java 版本
public int[] dailyTemperatures(int[] temperatures) {
int size = temperatures.length;
int[] res = new int[size];
Deque<Integer> deque = new ArrayDeque<>();
for (int i = 0; i < temperatures.length; i++) {
while (!deque.isEmpty() && temperatures[i] > temperatures[deque.peek()]) {
int front = deque.pop();
res[front] = i - front;
}
deque.push(i);
}
return res;
}
C++ 版本
vector<int> dailyTemperatures(vector<int>& temperatures) {
int size = temperatures.size();
vector<int> res(size);
stack<int> deque;
for (int i = 0; i < temperatures.size(); i++) {
while (!deque.empty() && temperatures[i] > temperatures[deque.top()]) {
int front = deque.top();
deque.pop();
res[front] = i - front;
}
deque.push(i);
}
return res;
}
递归方式:哪吒的“温度预言术”
如果你想用递归解决这个问题,可以试试分治法:
- 将数组分成两半,分别递归求解。
- 合并结果时,检查左半部分的每一天是否能找到右半部分的更高温度。
不过,递归的实现会比单调栈复杂得多,而且时间复杂度也会更高。所以,单调栈是更高效的选择。
总结
通过这两个问题,我们学会了:
- 栈的妙用:无论是括号匹配还是温度追踪,栈都能优雅地解决问题。
- 递归的思考方式:虽然递归不是最优解,但它能帮助我们更好地理解问题。
- 坚持的意义:就像哪吒一样,面对困难时,坚持思考和尝试,总能找到解决问题的办法。
希望这篇文章能让你在轻松愉快的氛围中学到知识。如果你觉得有用,别忘了点赞、收藏、转发三连哦!我是哪吒,下次再见!🚀