栈刷题+总结

文章目录

删除字符串中所有相邻重复项

题目链接

题解

  1. 用字符串模拟栈的行为,字符串的尾部插入和删除,并且这样得到的答案是不需要逆置的

代码

cpp 复制代码
class Solution 
{
public:
    string removeDuplicates(string s) 
    {
        string st;
        for(auto ch : s)
        {
            if(st.size() && ch == st.back())
            {
                st.pop_back();
            }
            else st.push_back(ch);
            // 栈为空或者栈顶和数组中的元素不同的情况
        }
        return st;
    }
};

比较含退格的字符串

题目链接

题解

  1. 用字符串模拟栈的行为,和上一题基本上是一样的套路

代码

cpp 复制代码
class Solution 
{
public:
    bool backspaceCompare(string s, string t) 
    {
        return cmpstring(s) == cmpstring(t);    
    }

    string cmpstring(string s)
    {
        string st;
        for(auto ch : s)
        {
            if(ch != '#') st += ch;
            else
            {
                // 处理字符串中只有#的情况
                if(st.size()) st.pop_back();
            }
        }
        
        return st; 
    }
};

基本计算器II

题目链接

题解

这题可以使用一个数组模拟 和一个变量存储运算符

  1. 遇到空格直接跳过
  2. 遇到数字,第一个数之前的运算符肯定是'+',因为题目说明了是非负整数,如果一个数字之前的符号是'+'或者是'-'就直接加入到栈中,如果是乘号或者是除号就取出栈顶的元素和下一个数进行计算,计算完后再把这个数字加入到栈中,最后栈里面的元素相加就是最终答案
  3. 遇到是运算符,就更新运算符,并且移动到下一个位置

代码

cpp 复制代码
class Solution 
{
public:
    int calculate(string s) 
    {
        // 空格的情况如何处理 -> i++
        // 表达式的基本上都会使用栈处理
       
        vector<int> st;
        char op = '+';
        int i = 0;
        int n = s.size();
        while(i < n)
        {
            if(s[i] == ' ') i++;
            else if(s[i] >= '0' && s[i] <= '9')
            {
                int tmp = 0;
                while(i < n && (s[i] >= '0'&& s[i] <= '9')) 
                tmp = tmp * 10 + (s[i++] - '0');
                // tmp可能是一个多位数
                if(op == '+') st.push_back(tmp);
                else if(op == '-') st.push_back(-tmp);
                else if(op == '*') st.back() *= tmp;
                else st.back() /= tmp;
                // 栈顶元素和下一个数相除,并且除完之后就等于重新加入栈顶了
            }
            else
            {
                op = s[i];
                i++;
            }
        }
        int ret = 0;
        for(auto x : st) ret += x;

        return ret;
    }
};

字符串解码

题目链接

题解

分情况讨论

  1. 先放入一个空串,防止出现取栈顶元素取不到的情况
  2. 遇到左括号,把字符串提取出来,放入栈中,而不是放入栈顶元素的后面,因为前面可能还有数字要加倍这个字符串
  3. 遇到右括号,把字符串的栈顶元素和数字栈的栈顶元素提取出来,进行加倍,这就是最近的匹配
  4. 遇到普通的前面不带数字的字符串,直接提取出来,放入字符串栈顶元素的后面

代码

cpp 复制代码
class Solution 
{
public:
    string decodeString(string s) 
    {
        stack<string> st;
        stack<int> ret;
        st.push("");

        int i = 0;
        int n = s.size();
        while(i < n)
        {
            if(s[i] >= '0' && s[i] <= '9')
            {
                int tmp = 0;
                while(i < n && (s[i] >= '0' && s[i] <= '9'))
                {
                    tmp = tmp * 10 + (s[i++] - '0'); 
                }
                ret.push(tmp);
            }
            else if(s[i] == '[')
            {
                i++;
                string p = "";
                while(i < n && s[i] >= 'a' && s[i] <= 'z')
                {
                    p += s[i++];
                }
                st.push(p);
            }
            else if(s[i] == ']')
            {
                int k = ret.top();
                ret.pop();
                string tmp = st.top();
                st.pop();
                while(k--)
                {
                   st.top() += tmp;
                }
                // 怎么把栈顶的字符串提取出来
                // st.top()
                i++;
            }
            else 
            {
                string q;
                while(i < n && s[i] >= 'a' && s[i] <= 'z')
                {
                    q += s[i++];
                }
                st.top() += q;
            }
        }

       return st.top();
    }
};

验证栈序列

题目链接

题解

  1. 保证让数据一直进栈
  2. 并且在进栈的同时,判断是否出栈
  3. 所有元素进栈完毕之后,如果popped的i == n说明栈合法,否则不合法,或者是栈为空,也是合法的,否则是不合法的

代码

cpp 复制代码
class Solution 
{
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) 
    {
        stack<int> st;
        int n = pushed.size();
        int i = 0;
        int j = 0;
        while(i < n)
        {
            st.push(pushed[i++]);
            while(!st.empty() && st.top() == popped[j])
            {
                st.pop();
                j++;
            }
        }
        
        return st.empty() ? true : false;
    }
};

总结

什么时候可以使用栈?

  1. 字符串表达式求值,括号匹配,删除相同的相邻元素,最近保存的先出去 ,都应该用栈来解决
  2. 需要处理最近或最后出现的数据
  3. 在DFS中,栈用于存储待访问的节点
  4. 检查字符串是否为回文
  5. 撤销操作: 需要支持回退功能

怎么使用栈解决问题?

  1. 模拟
  2. 用字符串或者数组模拟栈,st.back(),st.pop_back(),st.push_back()
  3. 分情况讨论

提取字符串中长数字字符转为整形的方法
int tmp = 0
int tmp = tmp * 10 + (s[i] - '0')
s[i] - '0' 防止溢出,tmp * 10 + s[i] 可能是超大的

相关推荐
Dann Hiroaki30 分钟前
文献分享: 对ColBERT段落多向量的剪枝——基于学习的方法
学习·算法·剪枝
三三木木七36 分钟前
神经网络的基本知识
人工智能·神经网络·算法
_extraordinary_37 分钟前
穷举vs暴搜vs深搜vs回溯vs剪枝刷题 + 总结
算法·深度优先·剪枝
studyer_domi41 分钟前
matlab 三维桥式起重机系统数学模型
人工智能·算法·matlab
曦月逸霜1 小时前
第十次CCF-CSP认证(含C++源码)
数据结构·c++·算法·ccf-csp
滨HI01 小时前
1314:【例3.6】过河卒(Noip2002)--DP>DFS【超时DFS】
算法·深度优先
Y编程小白1 小时前
JVM--垃圾回收
jvm·算法
KhalilRuan1 小时前
代码随想录-训练营-day52
算法
moz与京2 小时前
【附JS、Python、C++题解】Leetcode面试150题(9)——三数之和
javascript·c++·leetcode
nqqcat~2 小时前
函数的引用/函数的默认参数/函数的占位参数/函数重载
开发语言·c++·算法