力扣热题100-栈5题

124 阅读5分钟

20. 有效的括号

描述

Difficulty: 简单

Related Topics: , 字符串

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

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

示例 1:

输入:s = "()"
输出:true

示例 2:

输入:s = "()[]{}"
输出:true

示例 3:

输入:s = "(]"
输出:false

提示:

  • 1<=s.length<=1041 <= s.length <= 10^4
  • s 仅由括号 '()[]{}' 组成

思路说明

  • 遇到左括号就将匹配的右括号压入栈;
  • 遇到右括号则与栈顶元素比较,若不匹配则返回 false。

边界情况提示

  • "]" 这样的字符串开头就是右括号,栈为空,应返回 false。

Solution

class Solution {
public:
    bool isValid(string s) {
        stack<char>st;
        for(int i = 0; i < s.size(); i++){
            if(s[i] != '(' && s[i] != '[' && s[i] != '{'){
                if(st.empty()) return false;
                else {
                    char x = st.top(); st.pop();
                    if(x != s[i]) return false; 
                }
            } 
            else if(s[i] == '(') st.push(')');
            else if(s[i] == '[') st.push(']');
            else if(s[i] == '{') st.push('}');
        }
        return st.empty();
    }
};

155. 最小栈

描述

Difficulty: 中等

Related Topics: , 设计

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

  • MinStack() 初始化堆栈对象。
  • void push(int val) 将元素val推入堆栈。
  • void pop() 删除堆栈顶部的元素。
  • int top() 获取堆栈顶部的元素。
  • int getMin() 获取堆栈中的最小元素。

示例 1:

输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]

输出:
[null,null,null,null,-3,null,0,-2]

解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.getMin();   --> 返回 -2.

提示:

  • 231 <=val<=23112^{-31} <= val <= 2^{31} - 1
  • poptop 和 getMin 操作总是在 非空栈 上调用
  • push, pop, top,和 getMin最多被调用 31043 * 10^4 次

思路说明

  • 使用两个栈,一个正常存数据,另一个维护当前最小值;
  • 压入时如果比最小栈栈顶更小或相等,就同步压入最小栈;
  • 弹出时如果正好是最小值,两个栈都弹出。

Solution

class MinStack {
public:
    stack<int>st1,st2;
    MinStack() {
        
    }
    
    void push(int val) {
        st1.push(val);
        if(!st2.empty()){
            if(st2.top() >= val) st2.push(val);
        }
        else st2.push(val);
    }
    
    void pop() {
        if(!st2.empty()){
            if(st2.top() == st1.top()) st2.pop();
        }
        st1.pop();
    }
    
    int top() {
        return st1.top();
    }
    
    int getMin() {
        if(!st2.empty()) return st2.top();
        return st1.top();
    }
};

394. 字符串解码

描述

Difficulty: 中等

Related Topics: , 递归, 字符串

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

示例 1:

输入:s = "3[a]2[bc]"
输出:"aaabcbc"

示例 2:

输入:s = "3[a2[c]]"
输出:"accaccacc"

示例 3:

输入:s = "2[abc]3[cd]ef"
输出:"abcabccdcdcdef"

示例 4:

输入:s = "abc3[cd]xyz"
输出:"abccdcdcdxyz"

提示:

  • 1<=s.length<=301 <= s.length <= 30
  • s 由小写英文字母、数字和方括号 '[]' 组成
  • s 保证是一个 有效 的输入。
  • s 中所有整数的取值范围为 [1, 300] 

思路说明

  • 用两个栈:数字栈和字符串栈;
  • 遇到 [ 时将当前累计字符串入栈;
  • 遇到 ] 时拼接重复字符串。

Solution

class Solution {
public:
    string decodeString(string s) {
        string ss="";
        stack<int>st1;
        stack<string>st2;
        int n = 0;
        for(int i = 0; i < s.size(); i++){
            if(s[i] >= 'a' && s[i] <= 'z'){
                string x = "";
                x += s[i];
                if(st2.empty()) ss += s[i];
                else st2.push(x);
            }
            else if(s[i] == '['){
                st1.push(n); n = 0;
                string x = "";
                x += s[i];
                st2.push(x);
            }
            else if(s[i] == ']'){
                string x = "",y = ""; int m = st1.top(); st1.pop();
                while(st2.top() != "["){
                    x += st2.top(); st2.pop();
                }
                st2.pop();
                while(m--) y += x;
                if(st2.empty()) {
                    reverse(y.begin(), y.end());
                    ss += y;
                }
                else st2.push(y);
            }
            else n = n * 10 + (s[i] - '0');
        }
        return ss;
    }
};

739. 每日温度

描述

Difficulty: 中等

Related Topics: , 数组, 单调栈

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

示例 1:

输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]

示例 2:

输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]

示例 3:

输入: temperatures = [30,60,90]
输出: [1,1,0]

提示:

  • 1<= temperatures.length<=1051 <= temperatures.length <= 10^5
  • 30<= temperatures[i] <=10030 <= temperatures[i] <= 100

思路说明

  • 使用单调栈(存储索引值,栈内元素保持降序);
  • 如果当前温度大于栈顶索引所对应的温度,则弹出并计算间隔。

Solution

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        vector<int>ans(temperatures.size(), 0);
        stack<int>st; st.push(0);
        for(int i = 1; i < temperatures.size(); i++){
            while(!st.empty() && temperatures[i] > temperatures[st.top()]){
                ans[st.top()] = i - st.top(); st.pop();
            }
            st.push(i);
        }
        return ans;
    }
};

84. 柱状图中最大的矩形

描述

Difficulty: 困难

Related Topics: , 数组, 单调栈

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

示例 1:

输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10

示例 2:

输入: heights = [2,4]
输出: 4

提示:

  • 1<=heights.length<=1051 <= heights.length <=10^5
  • 0<=heights[i]<=1040 <= heights[i] <= 10^4

思路说明

  • 先在 heights 数组首尾加 0,可以避免边界特判;
  • 用单调递增栈,遇到下降即可确定右边界为i注意左边界需要是栈顶左边的下标
  • 知晓左右边界即可进行面积的计算

注意事项

  • 栈中存的是 pair<下标, 高度>
  • 弹出栈顶后 宽度 = 当前下标 - 栈顶新 top 的下标 - 1

Solution

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        stack<pair<int,int>>st; st.push({0,0});
        heights.insert(heights.begin(), 0); heights.push_back(0);
        int mx = 0;
        for(int i = 1; i < heights.size(); i++){
            if(heights[i] >= st.top().second){
                st.push({i, heights[i]});
                continue;
            }
            while(heights[i] < st.top().second){
                int x = st.top().second;st.pop();
                mx = max(mx, x * (i - st.top().first - 1));
            }
            st.push({i, heights[i]});
        }
        return mx;
    }
};