LeetCode-16day:栈

栈经典题目总结(C++实现)

栈是一种后进先出(LIFO)的数据结构,广泛应用于括号匹配、单调栈、字符串解码等问题。本文总结了五道经典的栈问题,帮助你更好地理解和掌握栈的应用。


🟢 1. 有效的括号(Valid Parentheses)

📄 题目描述:

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

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。

🧠 解题思路(简洁版)

  • 栈 + 哈希表
    • 使用栈存储最近遇到的左括号。
    • 遍历字符串,遇到右括号时检查栈顶是否匹配;若匹配则弹出栈顶,否则返回 false
    • 最终栈为空则括号有效。

⏱️ 复杂度分析

  • 时间复杂度:O(n),其中 n 为字符串长度。
  • 空间复杂度:O(n),栈空间。

✅ C++ 实现

cpp 复制代码
class Solution {
public:
    bool isValid(string s) {
        int n = s.size();
        if (n % 2 == 1) {
            return false;
        }
        unordered_map<char, char> pairs = {
            {')', '('},
            {']', '['},
            {'}', '{'}
        };
        stack<char> stk;
        for (char ch : s) {
            if (pairs.count(ch)) {
                if (stk.empty() || stk.top() != pairs[ch]) {
                    return false;
                }
                stk.pop();
            } else {
                stk.push(ch);
            }
        }
        return stk.empty();
    }
};

🟢 2. 最小栈(Min Stack)

📄 题目描述:

设计一个支持 pushpoptopgetMin 操作的栈,所有操作的时间复杂度为 O(1)

🧠 解题思路(简洁版)

  • 辅助栈
    • 使用两个栈:x_stack 存储所有元素,min_stack 存储当前最小值。
    • 每次压入元素时,更新 min_stack 的栈顶为当前最小值。
    • 弹出元素时,两个栈同步操作。

⏱️ 复杂度分析

  • 时间复杂度:O(1),所有操作均为常数时间。
  • 空间复杂度:O(n),辅助栈的空间。

✅ C++ 实现

cpp 复制代码
class MinStack {
    stack<int> x_stack;
    stack<int> min_stack;

public:
    MinStack() {
        min_stack.push(INT_MAX);
    }

    void push(int val) {
        x_stack.push(val);
        min_stack.push(min(min_stack.top(), val));
    }

    void pop() {
        x_stack.pop();
        min_stack.pop();
    }

    int top() {
        return x_stack.top();
    }

    int getMin() {
        return min_stack.top();
    }
};

🟢 3. 字符串解码(Decode String)

📄 题目描述:

给定一个经过编码的字符串,返回其解码后的字符串。编码规则为:k[encoded_string],其中 k 是正整数,表示 encoded_string 重复 k 次。

🧠 解题思路(简洁版)

  • 栈 + 模拟
    • 使用栈存储字符串片段。
    • 遍历输入字符串,处理数字、字母和括号:
      • 数字:提取并压入栈。
      • 字母或 [:直接压入栈。
      • ]:弹出栈中的子串并反转,获取重复次数,重复拼接后压入栈。
    • 最终将栈中的所有字符串拼接成结果。

⏱️ 复杂度分析

  • 时间复杂度:O(n),其中 n 为输入字符串长度。
  • 空间复杂度:O(n),栈空间。

✅ C++ 实现

cpp 复制代码
class Solution {
public:
    string getDigits(string &s, size_t &ptr) {
        string ret = "";
        while (isdigit(s[ptr])) {
            ret.push_back(s[ptr++]);
        }
        return ret;
    }

    string getString(vector<string> &v) {
        string ret;
        for (const auto &s : v) {
            ret += s;
        }
        return ret;
    }

    string decodeString(string s) {
        vector<string> stk;
        size_t ptr = 0;
        while (ptr < s.size()) {
            char cur = s[ptr];
            if (isdigit(cur)) {
                string digits = getDigits(s, ptr);
                stk.push_back(digits);
            } else if (isalpha(cur) || cur == '[') {
                stk.push_back(string(1, s[ptr++]));
            } else {
                ptr++;
                vector<string> sub;
                while (stk.back() != "[") {
                    sub.push_back(stk.back());
                    stk.pop_back();
                }
                reverse(sub.begin(), sub.end());

                stk.pop_back();

                int repTime = stoi(stk.back());
                stk.pop_back();
                string t, o = getString(sub);

                while (repTime--) t += o;
                stk.push_back(t);
            }
        }
        return getString(stk);
    }
};

🟢 4. 每日温度(Daily Temperatures)

📄 题目描述:

给定一个整数数组 temperatures,表示每天的温度。返回一个数组 answer,其中 answer[i] 是从第 i 天开始,直到再次出现更高的温度的天数。如果不存在更高的温度,则 answer[i] 为 0。

🧠 解题思路(简洁版)

  • 单调栈
    • 使用栈存储温度数组的索引。
    • 遍历温度数组,对于每个温度:
      • 若当前温度高于栈顶索引对应的温度,则更新答案并弹出栈顶。
      • 将当前索引入栈。
    • 最终栈中剩余的索引对应的答案为 0。

⏱️ 复杂度分析

  • 时间复杂度:O(n),每个索引最多入栈和出栈一次。
  • 空间复杂度:O(n),栈空间。

✅ C++ 实现

cpp 复制代码
class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        int n = temperatures.size();
        vector<int> ans(n);
        stack<int> s;
        for (int i = 0; i < n; i++) {
            while (!s.empty() && temperatures[i] > temperatures[s.top()]) {
                int previousIndex = s.top();
                ans[previousIndex] = i - previousIndex;
                s.pop();
            }
            s.push(i);
        }
        return ans;
    }
};

🟢 5. 柱状图中最大的矩形(Largest Rectangle in Histogram)

📄 题目描述:

给定一个非负整数数组 heights,表示柱状图中各个柱子的高度。计算柱状图中最大的矩形面积。

🧠 解题思路(简洁版)

  • 单调栈
    • 使用单调栈分别计算每个柱子的左边界和右边界。
    • 左边界:从左到右遍历,栈内存储递增的柱子索引。
    • 右边界:从右到左遍历,栈内存储递增的柱子索引。
    • 计算每个柱子的最大矩形面积:(right[i] - left[i] - 1) * heights[i]

⏱️ 复杂度分析

  • 时间复杂度:O(n),每个柱子最多入栈和出栈一次。
  • 空间复杂度:O(n),栈空间。

✅ C++ 实现

cpp 复制代码
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n = heights.size();
        vector<int> left(n), right(n);

        stack<int> mono_stack;
        for (int i = 0; i < n; i++) {
            while (!mono_stack.empty() && heights[mono_stack.top()] >= heights[i]) {
                mono_stack.pop();
            }
            left[i] = (mono_stack.empty() ? -1 : mono_stack.top());
            mono_stack.push(i);
        }
        mono_stack = stack<int>();
        for (int i = n - 1; i >= 0; i--) {
            while (!mono_stack.empty() && heights[mono_stack.top()] >= heights[i]) {
                mono_stack.pop();
            }
            right[i] = (mono_stack.empty() ? n : mono_stack.top());
            mono_stack.push(i);
        }
        int ans = 0;
        for (int i = 0; i < n; i++) {
            ans = max(ans, (right[i] - left[i] - 1) * heights[i]);
        }
        return ans;
    }
};

📌 总结

题目 方法 时间复杂度 空间复杂度
有效的括号 栈 + 哈希表 O(n) O(n)
最小栈 辅助栈 O(1) O(n)
字符串解码 栈 + 模拟 O(n) O(n)
每日温度 单调栈 O(n) O(n)
柱状图中最大的矩形 单调栈 O(n) O(n)

希望本文对你有所帮助!如果你还有其他问题,欢迎继续提问。

相关推荐
pengzhuofan4 分钟前
Java设计模式-建造者模式
java·设计模式·建造者模式
月殇_木言24 分钟前
算法基础 第3章 数据结构
数据结构·算法
夕四丶1 小时前
【java实现一个接口多个实现类通用策略模式】
java·策略模式
找不到、了1 小时前
Java设计模式之《策略模式》
java·设计模式·策略模式
刘火锅1 小时前
设计模式-策略模式 Java
java·设计模式·策略模式
亮亮爱刷题1 小时前
算法提升之树上问题-(LCA)
数据结构·算法·leetcode·深度优先
火车叨位去19491 小时前
力扣top100(day03-01)--二叉树 03
算法·leetcode·职场和发展
岁忧1 小时前
(LeetCode 每日一题) 1780. 判断一个数字是否可以表示成三的幂的和 (数学、三进制数)
java·c++·算法·leetcode·职场和发展·go
一颗星的征途2 小时前
java循环分页查询数据,任何把查询到的数据,分批处理,多线程提交到数据库清洗数据
java·数据库·mysql·spring cloud