【算法】栈专题

一. (1047.) 删除字符串中的所有相邻重复项

算法原理:

关键点是当前元素是否被消除,需要知道上一个元素的信息。完美符合栈的特性,后进先出,后入栈的元素和栈顶元素相比较,等于就使栈顶元素出栈,不等于就自己进栈,但本题要求返回string,用栈得到结果后还要转化为string,可以直接用数组来模拟栈,在数组的尾部进行尾插尾删,实现栈的进栈和出栈

cpp 复制代码
class Solution {
public:
    string removeDuplicates(string s) {
        string ret;//用数组模拟栈
        for(auto c:s)
        {//注意字符串为空时会非法访问
            if(ret.size()&&c==ret.back()) ret.pop_back();//模拟出栈
            else ret+=c;//模拟入栈
        }
        return ret;
    }
};

二. (844.) 比较含退格的字符串

算法原理:

由于退格的时候需要知道前⾯元素的信息,⽽且退格也符合后进先出的特性。因此我们可以使⽤「栈」结构来模拟退格的过程。与上题思路相同

当遇到⾮ # 字符的时候,直接进栈;

当遇到 # 的时候,栈顶元素出栈

cpp 复制代码
class Solution {
public:
    bool backspaceCompare(string s, string t) {
        string ret1,ret2;
        for(auto c:s)
        {
            if(ret1.size()&&c=='#') ret1.pop_back();//字符串为空时不需要退格
            if(c!='#') ret1+=c;//结果中部包含退格
        }
        for(auto c:t)
        {
            if(ret2.size()&&c=='#') ret2.pop_back();
            if(c!='#') ret2+=c;
        }
        if(ret1==ret2) return true;
        else return false;
    }
};

三. (227.) 基本计算器 II

算法原理:

本题表达式中没有括号,只用处理加减乘除混合运算即可,先乘除后加减。分情况讨论,表达式中字符只有三种情况,分别为空格、运算符和数字,数字注意要提取链接起来,因为有可能是多位数的运算。可以先设置一个变量记为'+',每遇到运算符就更新。用数组模拟的栈中存储元素,遇到乘除就及时计算,减号就转化为负数入栈,最终就可以不用考虑每个数之间的加减关系,全部相加即为结果。

除此之外还有两栈处理和逆波兰表达式的思路

cpp 复制代码
class Solution {
public:
    int calculate(string s) {
        vector<int> st;//用数组模拟栈
        char c='+';//保存每一个数的前一个符号
        int i=0;
        while(i<s.size())
        {
            //分三种情况讨论
            if(s[i]==' ') i++;//1.为空格时
            else if(s[i]>='0'&&s[i]<='9')//2.为数字时
            {
                  //提取数字
                   int tmp=0;//每次循环前tmp必须重置,因为tmp值涉及前一值和当前值
                    while(i<s.size()&&s[i]>='0'&&s[i]<='9') tmp=(tmp*10+(s[i++]-'0'));

                    if(c=='+') st.push_back(tmp);
                    else if(c=='-') st.push_back(-tmp);
                    else if(c=='*') st.back()*=tmp;
                    else st.back()/=tmp;
            }
            else{//3.为运算符时
                c=s[i++];
            }
        }
        //同一加法处理返回值
        int ret=0;
        for(auto n:st) ret+=n;
        return ret;
    }
};

四. (394.) 字符串解码

算法原理:

注意:

1.用双栈来实现,每次遇到']'时拿出字符栈顶元素(记为m)和数字字符栈顶元素(记为n),让m拼接n次,pop掉字符和数字栈原来的栈顶元素,push到新的栈顶元素后

2.当遍历到左右括号时要跳过括号进行提取操作

3.提取字符串与提取数字的操作相同

其余细节见代码

cpp 复制代码
class Solution {
public:
    string decodeString(string s) {
        stack<int> nums;
        stack<string> st;
        st.push("");//防止越界
        int i=0,n=s.size();//遍历s的下标
        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');
            nums.push(tmp);
           }
            //遇到'[',提取字符入栈
            else if(s[i]=='[')
            {
                i++;//跳过括号
                string str;
                while(i<n&&s[i]>='a'&&s[i]<='z') str+=s[i++];
                st.push(str);
            }
          
            //判断括号,右括号第一次出现
            else if(s[i]==']'){
                string str=st.top();//拼接重复字符串
                int k=nums.top();
                nums.pop();//用完数字和字符栈顶元素后要删除
                 st.pop();
                while(k--)
                { //将拼接后字符串放入上一个栈元素后面
                    st.top()+=str;
                }
                i++;//跳过右括号
            }

            //遇到单独的字符,提取出来放到st栈顶元素后
            else while(i<n&&s[i]>='a'&&s[i]<='z')   st.top()+=s[i++];
              
        }
        return st.top();
    }
};

五. (946. 验证栈序列)

算法思路:

⽤栈来模拟进出栈的流程。

⼀直让元素进栈,进栈的同时判断是否需要出栈。当所有元素模拟完毕之后,如果栈中还有元素,那么就是⼀个⾮法的序列。否则,就是⼀个合法的序列。或者用出栈的指针判断是否遍历完数组,完则正确,反之

cpp 复制代码
class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
        vector<int> st;//模拟栈
        int i=0;//弹出数组指针
        for(auto n:pushed)
        {
            st.push_back(n);
            while(i<popped.size()&&!st.empty()&&st.back()==popped[i]) st.pop_back(),i++;
            //else st.push_back(n);
        }
        if(st.empty()) return true;
        else return false;
    }
};
相关推荐
haogexiaole2 小时前
资源图分配算法
算法
天选之女wow2 小时前
【代码随想录算法训练营——Day6(Day5周日休息)】哈希表——242.有效的字母异位词、349.两个数组的交集、202.快乐数、1.两数之和
数据结构·算法·leetcode·散列表
寒冬没有雪2 小时前
利用归并算法对链表进行排序
c++·算法
CoovallyAIHub2 小时前
AI帮你打标签!这个开源神器让数据标注快了90%
深度学习·算法·计算机视觉
古译汉书2 小时前
蓝桥杯算法之基础知识(7)---排序题的快排和归并排序
算法
JJJJ_iii2 小时前
【左程云算法07】队列和栈-链表数组实现
数据结构
晴天下小雨o2 小时前
Json-rpc通信项目(基于C++ Jsoncpp muduo库)
c++·rpc·json
EnzoRay2 小时前
C++学习笔记(二)
c++
薛定谔的算法2 小时前
JavaScript队列实现详解:从基础到性能优化
javascript·数据结构·算法