挑战刷leetcode第23天(栈-有效的括号+每日温度)

5 阅读4分钟

哪吒教你用栈搞定括号匹配和每日温度问题:从入门到入土

大家好,我是哪吒,今天咱们来聊聊两个经典的算法问题:有效的括号每日温度。这两个问题看似简单,但背后隐藏的栈思想却非常巧妙。我会用幽默搞笑的方式,带你一步步理解它们的实现思路,顺便教你用 Java 和 C++ 写出优雅的代码。


1. 有效的括号:哪吒的“括号大冒险”

问题描述

给定一个只包含 '('')''{''}''['']' 的字符串,判断它是否有效。有效字符串需要满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

哪吒的思路

想象一下,你是一个括号管理员,手里拿着一堆括号卡片。每次遇到一个左括号(比如 ({[),你就把它对应的右括号(比如 )}])放进一个“魔法栈”里。当你遇到一个右括号时,就从栈顶取出一个卡片,看看是否匹配。

  • 如果匹配,继续;
  • 如果不匹配,或者栈空了,说明这个字符串无效。

最后,如果栈空了,说明所有括号都匹配成功,字符串有效;否则,无效。

代码实现

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();
}

递归方式:哪吒的“套娃大法”

如果你觉得栈还不够酷,可以试试递归。递归的核心思想是:

  1. 每次遇到左括号,递归处理后面的字符串。
  2. 遇到右括号时,检查是否与当前左括号匹配。
  3. 如果匹配,继续递归;否则,返回失败。

不过,递归的实现会比栈复杂一些,而且容易栈溢出(毕竟递归深度和字符串长度成正比)。所以,栈是更优雅的选择。


2. 每日温度:哪吒的“温度追踪器”

问题描述

给定一个整数数组 temperatures,表示每天的温度,返回一个数组 answer,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。

哪吒的思路

这个问题可以用单调栈来解决。单调栈的核心思想是:

  1. 维护一个栈,栈里存放的是“还没有找到更高温度的日期索引”。

  2. 遍历温度数组,对于每一天的温度:

    • 如果当前温度比栈顶的温度高,说明栈顶的那一天找到了更高温度,计算天数差,并更新结果数组。
    • 重复上述过程,直到栈为空或当前温度不大于栈顶温度。
  3. 最后,将当前日期的索引压入栈中。

代码实现

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;
}

递归方式:哪吒的“温度预言术”

如果你想用递归解决这个问题,可以试试分治法:

  1. 将数组分成两半,分别递归求解。
  2. 合并结果时,检查左半部分的每一天是否能找到右半部分的更高温度。

不过,递归的实现会比单调栈复杂得多,而且时间复杂度也会更高。所以,单调栈是更高效的选择。


总结

通过这两个问题,我们学会了:

  1. 栈的妙用:无论是括号匹配还是温度追踪,栈都能优雅地解决问题。
  2. 递归的思考方式:虽然递归不是最优解,但它能帮助我们更好地理解问题。
  3. 坚持的意义:就像哪吒一样,面对困难时,坚持思考和尝试,总能找到解决问题的办法。

希望这篇文章能让你在轻松愉快的氛围中学到知识。如果你觉得有用,别忘了点赞、收藏、转发三连哦!我是哪吒,下次再见!🚀