【算法训练笔记】栈的OJ题

        欢迎来到小林的博客!!
      ️博客主页:✈️林 子
      ️博客专栏:✈️ 小林的算法训练笔记
      ️社区 :✈️ 进步学堂
      ️欢迎关注:点赞收藏✍️留言

目录

  • 1047. 删除字符串中的所有相邻重复项
  • 844. 比较含退格的字符串
  • 227. 基本计算器 II
  • 394. 字符串解码
  • 946. 验证栈序列

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

题目链接:1047. 删除字符串中的所有相邻重复项

题目描述:

给出由小写字母组成的字符串 S重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。

提示:

  1. 1 <= S.length <= 20000
  2. S 仅由小写英文字母组成。

解题思路:

我们只需要把字符入栈,每次入栈前和栈顶元素进行比较,如果字符相同则把栈顶POP掉,并且此次元素也不Push,这样即完成一次删除操作。反之则把元素push入栈。 因为返回值是一个字符串,所以我们可以拿字符串来模拟栈,尾删对应的是出栈,尾插对应的是入栈。

动图详解:

【算法训练笔记】栈的OJ题_第1张图片

代码:

class Solution {
public:
    string removeDuplicates(string s) {
        string st;//用字符串模拟栈
        for(auto& ch : s)
        {
            if(st.size() > 0 && st.back() == ch)
            {
                st.pop_back();
            }else
            {
                st.push_back(ch);
            }
        }
        return st;
    }
};

运行结果:

【算法训练笔记】栈的OJ题_第2张图片

844. 比较含退格的字符串

题目链接:844. 比较含退格的字符串

题目描述:

给定 st 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true# 代表退格字符。

**注意:**如果对空文本输入退格字符,文本继续为空。

示例 1:

输入:s = "ab#c", t = "ad#c"
输出:true
解释:s 和 t 都会变成 "ac"。

示例 2:

输入:s = "ab##", t = "c#d#"
输出:true
解释:s 和 t 都会变成 ""。

示例 3:

输入:s = "a#c", t = "b"
输出:false
解释:s 会变成 "c",但 t 仍然是 "b"。

提示:

  • 1 <= s.length, t.length <= 200
  • st 只含有小写字母以及字符 '#'

解题思路:

和上一题是一样的,只不过这次我们是遇到#则删除前一个。而上一题是当前字符和栈顶字符相等则删除栈顶字符,这个则是遇到#删除栈顶字符。然后两个字符串都做一次上面那道题的操作,然后比较一小是否相等即可,不过这里也有一个小细节,那就是#号可以出现在第一个字符,这里需要特殊判断一下。因为步骤和上面几乎一模一样,所以动图就不画了,搞懂了上一题这一题自然也能秒懂。

代码:

class Solution {
public:
    bool backspaceCompare(string s, string t) {
        string st1; //存储s
        string st2; //存储t
        for(auto& ch : s)
        {
            if(st1.size() > 0 && ch == '#') st1.pop_back();
            else if(ch != '#') st1.push_back(ch);
        }
        //和上面操作一模一样
        for(auto& ch : t)
        {
            if(st2.size() > 0 && ch == '#') st2.pop_back();
            else if(ch != '#')st2.push_back(ch); //#符号不能入栈
        }
        return st1 == st2; //相等返回true
    }
};

运行结果:

【算法训练笔记】栈的OJ题_第3张图片

227. 基本计算器 II

题目链接:227. 基本计算器 II

题目描述:

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

整数除法仅保留整数部分。

你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。

**注意:**不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval()

示例 1:

输入:s = "3+2*2"
输出:7

示例 2:

输入:s = " 3/2 "
输出:1

示例 3:

输入:s = " 3+5 / 2 "
输出:5

提示:

  • 1 <= s.length <= 3 * 105
  • s 由整数和算符 ('+', '-', '*', '/') 组成,中间由一些空格隔开
  • s 表示一个 有效表达式
  • 表达式中的所有整数都是非负整数,且在范围 [0, 231 - 1]
  • 题目数据保证答案是一个 32-bit 整数

解题思路

因为这运算只有 +,-,*,/四则运算。所以我们只需要用一个栈来存储数据,再用一个char op变量来存储符号。当走到数字的时候遇到 X 或者 / 号。那么就从栈中pop出2个数据。进行运算后再重新放回队列,如果记录的是-号。那么我们往队列push的值需要 乘上一个-1。到最后再把栈里的值全部相加起来即可。这里需要注意一个小细节,就是我们的op需要初始化成’+'号。因为只有op为’+‘ ,我们才会把数据push进栈中。

比如下面有一个例子,3+2*2-5 ,我们来动图模拟一下。

【算法训练笔记】栈的OJ题_第4张图片

还有一点要注意的是,leetcode给的数据中是有可能会包含空格,所以遇到空格我们要跳过。

【算法训练笔记】栈的OJ题_第5张图片

代码:

class Solution {
public:
    int calculate(string s) {
        char op = '+';
        stack<int> st;
        int n = s.size(), i = 0;
        while(i < n)
        {
            if(s[i] == ' ') i++;  //跳过空格
            else if(s[i] >= '0' && s[i] <= '9')
            {
                //遇到数据了,数据可能是多位数,所以我们要全部截取
                int val = 0; 
                while(s[i] >= '0' && s[i] <= '9') val = val * 10 + (s[i++] - 48); 

                //如果op是+号,我们要入栈,如果是-号,我们需要 * -1 再入栈,如果是 * 和 / 先出栈,再val和出栈的数进行运算
                if(op == '+')
                    st.push(val);
                else if(op == '-')
                    st.push(val* -1);
                else 
                {
                    //是 * 和 / ,我们把栈顶元素拿出来运算,运算完再push到栈中
                    int top = st.top();
                    st.pop();
                    switch(op)
                    {
                        case '*' : st.push(top * val);  break;
                        case '/' : st.push(top/val); break;
                    }
                }
            }else 
            {
                //遇到符号了,直接替换符号
                op = s[i++]; 
            }
        }

        //把栈中的元素全部取出来相加
        int sum = 0 ;
        while(!st.empty())
        {
            sum += st.top();
            st.pop();
        }
        return sum;
    }
};

运行结果:

【算法训练笔记】栈的OJ题_第6张图片

394. 字符串解码

题目链接:字符串解码

题目描述:

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

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

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

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a2[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 <= 30
  • s 由小写英文字母、数字和方括号 '[]' 组成
  • s 保证是一个 有效 的输入。
  • s 中所有整数的取值范围为 [1, 300]

解题思路:

这一题我们依旧要用栈来解决,我们需要用2个栈,一个栈用来存放数字,一个栈用来存放字符串。当遇到数字时,提取数字并入数字栈。当遇到[号时,提取字符串并入字符栈。当遇到]时,也就是解码。我们需要从字符栈种拿字符,从数字栈种拿数字。随机拼接成一个新字符串,把新字符串接入到上一个栈顶的后面。我们分四种情况讨论。

情况1:遇到数字

遇到数字,那么数字可能也是多个字符串组成,所以我们需要把数字提取出来,放入 nums栈中。

情况2:遇到 [

遇到[说明要开始提取字符了,那么从当前下标的下一个位置开始提取字符串。提取完字符串后入到 strs栈中。

情况3:遇到 ]

遇到 [ 说明我们要开始解密了,我们分别提取strs栈和nums栈中的栈顶。获得一个数字k和一个字符串str。我们循环k次,每次循环都加上一个str。最后需要把strs接到栈顶的尾部,因为我们不确定前面是否还有字符。

情况4:遇到字符

遇到字符说明数字只有1,所以我们只需要把字符提取出来,接入到strs栈顶的尾部即可。

需要注意一些小细节,那就是当strs栈为空的时候,我们是无法把字符串接入到栈顶的。所以我们一开始需要push一个空串进strs栈。这样后面的字符串往空串后面拼接,还是原来的样子。

动图演示:

【算法训练笔记】栈的OJ题_第7张图片

动图中没有显示空串,其实最底下是有个空串的。否则后面的cacacacacaca接入到栈顶元素尾部是会报错的。

代码:

class Solution {
public:
    string decodeString(string s) {
        stack<int> nums;
        stack<string> strs; 
        strs.push(""); //先让空串入栈
        int i = 0 , n = s.size();
        while(i < n)
        {
            //第一种情况,如果遇到数字
            if(s[i] >= '0' && s[i] <= '9')
            {
                int val = 0;
                //拼接所有数字
                while(s[i] >= '0' && s[i] <= '9') val = val * 10 + (s[i++] - 48); 
                //拼接完数字入栈
                nums.push(val);
            }
            else if(s[i] == '[') //第二章情况,遇到 [ 
            {
                //从i的下一个位置开始提取字符
                string val; 
                i++; 
                while(s[i] >= 'a' && s[i] <= 'z')val += s[i++]; 
                //提取的字符入栈
                strs.push(val);
            }else if(s[i] == ']') // 第三种情况,遇到 ]
            {
                //分别从nums和strs中提取栈顶元素
                int k = nums.top();
                nums.pop();
                string tmp = strs.top();
                strs.pop();

                //将 k 次 tmp字符串接入到strs栈顶的尾部
                while(k--)
                {
                    strs.top() += tmp;
                }
                i++; //跳到下一个位置
            }else{
                //第四种情况,遇到字符
                //直接提取字符,接入到栈顶尾部
                string val; 
                while(i < n && s[i] >= 'a' && s[i] <= 'z')val += s[i++]; 
                //接入到栈顶尾部
                strs.top() += val;
            }
        }
        return strs.top(); //返回栈顶元素
    }
};

运行结果:

【算法训练笔记】栈的OJ题_第8张图片

946. 验证栈序列

题目链接: 946. 验证栈序列

题目描述:

给定 pushedpopped 两个序列,每个序列中的 值都不重复,只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时,返回 true;否则,返回 false

示例 1:

输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1

示例 2:

输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出:false
解释:1 不能在 2 之前弹出。

提示:

  • 1 <= pushed.length <= 1000
  • 0 <= pushed[i] <= 1000
  • pushed 的所有元素 互不相同
  • popped.length == pushed.length
  • poppedpushed 的一个排列

解题思路:

我们可以用一个指针指向popped数组,然后疯狂让pushed数组的值入栈。然后监测栈顶元素是否等于当前指向的popped元素。如果等于则说明出栈,一直出栈到栈顶元素不等于popped为止。最后如果栈的元素不为空,说明出栈顺序是错误的。反之则是正确的。

动图演示:

【算法训练笔记】栈的OJ题_第9张图片

如果循环结束,栈为空,则说明poped的出栈顺序是正确的。反之则说明是错误的。

代码:

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

运行结果:

【算法训练笔记】栈的OJ题_第10张图片

你可能感兴趣的:(算法训练笔记,算法,笔记)