【算法】栈专题

一. (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;
    }
};
相关推荐
Thera7776 分钟前
【Linux C++】彻底解决僵尸进程:waitpid(WNOHANG) 与 SA_NOCLDWAIT
linux·服务器·c++
Wei&Yan10 分钟前
数据结构——顺序表(静/动态代码实现)
数据结构·c++·算法·visual studio code
wregjru25 分钟前
【QT】4.QWidget控件(2)
c++
浅念-30 分钟前
C++入门(2)
开发语言·c++·经验分享·笔记·学习
小羊不会打字38 分钟前
CANN 生态中的跨框架兼容桥梁:`onnx-adapter` 项目实现无缝模型迁移
c++·深度学习
团子的二进制世界44 分钟前
G1垃圾收集器是如何工作的?
java·jvm·算法
Max_uuc1 小时前
【C++ 硬核】打破嵌入式 STL 禁忌:利用 std::pmr 在“栈”上运行 std::vector
开发语言·jvm·c++
吃杠碰小鸡1 小时前
高中数学-数列-导数证明
前端·数学·算法
故事不长丨1 小时前
C#线程同步:lock、Monitor、Mutex原理+用法+实战全解析
开发语言·算法·c#
long3161 小时前
Aho-Corasick 模式搜索算法
java·数据结构·spring boot·后端·算法·排序算法