C++算法:栈

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

显然,删除重复项类似栈操作。当栈顶元素与待插入元素相同时,出栈并遍历下一个字符,完成删除重复项。如果直接使用stack,最后既要出栈,又要把结果逆序,可以用string模拟栈。

cpp 复制代码
class Solution {
public:
    string removeDuplicates(string s)
    {
        string ret;
        for (char e : s)
        {
            if (ret.size() != 0 && ret.back() == e)
                ret.pop_back();
            else
                ret += e;
        }
        return ret;
    }
};

2.比较含退格的字符串

与上题类似,用数组模拟栈。

cpp 复制代码
class Solution {
public:
    bool backspaceCompare(string s, string t)
    {
        return changStr(s) == changStr(t);
    }
    string changStr(string& s)
    {
        string ret;
        for (char e : s)
        {
            if (e != '#')
                ret += e;
            if (ret.size() && e == '#')
                ret.pop_back();
        }
        return ret;
    }
};

3.基本计算器II

用栈实现计算器是一类复杂的题型,力扣上的这道题是比较简单的,运算的式子没有包含括号,优先级只需要考虑乘除。对于这道题可以直接使用栈,也可以用数组模拟栈。

一般是要用两个栈,一个int存储数字,一个char记录加减乘除等操作。这题比较简单只需要一个栈存储数字,一个char变量op记录加减乘除。op初始化为'+',如果op='+',则数字直接入栈;如果op='-',则相反数入栈;如果op为乘或除,则栈顶元素乘除上当前遍历到的数字。最后栈中的元素为乘除计算后的数字,将栈中元素累加即是最终结果。

cpp 复制代码
class Solution5 {
public:
    int calculate(string s)
    {
        vector<int> st;
        int n = s.size();
        char op = '+';
        int i = 0;
        while (i < n)
        {
            if (s[i] == ' ')//忽略空格
                i++;
            else if (s[i] >= '0' && s[i] <= '9')
            {
                int t = 0;
                while (i < n && s[i] >= '0' && s[i] <= '9')//把单个数字和连续的数字字符转成整数
                    t = t * 10 + (s[i++] - '0');
                
                if (op == '+')
                    st.push_back(t);
                else if (op == '-')
                    st.push_back(-t);
                else if (op == '*')
                    st.back() *= t;
                else
                    st.back() /= t;
            }
            else
                op = s[i++];
        }
        int ret = 0;
        for (int& e : st)
            ret += e;
        return ret;
    }
};

4.字符串解码

栈的类型题往往处理的细节比较多,这道题需要处理数字子串、方括号、方括号内的子串、方括号外的字母子串以及最棘手的嵌套解码。

解决这道题需要两个栈,一个string类型的栈,初始时先放入一个空串,最后的栈顶元素即为所求,一个int类型用于把数字子串转成整数的栈。整体思路是遇到数字则转成整数放入int栈;每遇到 则创建字符串,直到遇到 ,把得到的方括号内的字符串放入string栈。遇到 ] 则取栈顶元素进行解码并pop栈顶元素,把解码后的字符串尾插到栈顶元素。如果没有遇到 [ ,直接遇到字母,则尾插到栈顶元素。

cpp 复制代码
class Solution7 {
public:
    string decodeString(string s)
    {
        int i = 0, n = s.size();
        stack<int> num;
        stack<string> str;
        str.push("");

        while (i < n)
        {
            if (s[i] >= '0' && s[i] <= '9') //数字子串转整数
            {
                int t = 0;
                while (s[i] >= '0' && s[i] <= '9')
                    t = t * 10 + (s[i++] - '0');
                num.push(t);
            }
            else if (s[i] == '[') //遇到 [ 就要创建元素放入string栈
            {
                i++;
                string tmp;
                while (s[i] >= 'a' && s[i] <= 'z')
                    tmp += s[i++];
                str.push(tmp);
            }
            else if (s[i] == ']') //进行一层解码
            {
                i++;
                string tmp = str.top();
                str.pop();
                int k = num.top();
                num.pop();
                while (k--)
                    str.top() += tmp;
            }
            else
            {
                while (i < n && s[i] >= 'a' && s[i] <= 'z')
                    str.top() += s[i++];
            }
        }
        return str.top();
    }
};

5.验证栈序列

让pushed中的元素一直进栈,当栈顶元素与poppedi相等时出栈。如果popped序列正确,则最终i==n,或者栈为空。

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