当前位置: 首页 > news >正文

算法分析 —— 《栈》

文章目录

  • 删除字符串中的所有相邻重复项
    • 题目描述:
    • 代码实现:
    • 代码解析:
  • 比较含退格的字符串
    • 题目描述:
    • 代码实现:
    • 代码解析:
  • [基本计算器 II](https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/)
    • 题目描述:
    • 代码实现:
    • 代码解析:
  • 字符串解码
    • 题目描述:
    • 代码实现:
    • 代码解析:
  • 验证栈序列
    • 题目描述:
    • 代码实现:
    • 代码解析:

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

题目描述:

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

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

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

示例:

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

代码实现:

class Solution 
{
public:
    string removeDuplicates(string s) 
    {
        string st;
        for(auto& x : s)
        {
            if(st.size() && st.back() == x) st.pop_back();
            else st.push_back(x);
        }
        return st;
    }
};

代码解析:

这道题就是一道消消乐,当两个相邻一样得字符一样,那就直接消除掉,所以我们可以结合之前刷过的题来看,我们可以运用“栈”这个数据结构,来帮助我们完成消消乐。

但是栈这个数据结构还是太大了,所以对于都是小写字母得这道题来说,我们直接使用字符串来模拟就好了。

所以我们直接遍历整个字符串,如果该元素与栈顶元素一致,那就直接删掉栈顶元素。

否则直接加进到栈里即可。

比较含退格的字符串

题目描述:

给定 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"。

代码实现:

class Solution 
{
public:
    bool backspaceCompare(string s, string t) 
    {
        string st1, st2;
        for(auto& ch : s)
        {
            if(st1.size() && ch == '#') st1.pop_back();
            else if(ch != '#') st1 += ch;
        }

        for(auto& ch : t)
        {
            if(st2.size() && ch == '#') st2.pop_back();
            else if(ch != '#') st2 += ch;
        }
        return st1 == st2;
    }
};

代码解析:

题目意思和上面那道题差不多, 本质还是个小的消消乐,在这里我就不过多赘述了。

基本计算器 II

题目描述:

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

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

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

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

示例 1:

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

示例 2:

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

示例 3:

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

代码实现:

class Solution 
{
public:
    int calculate(string s) 
    {
        vector<int> st;
        char op = '+';
        for(int i = 0; i < s.size(); )
        {
            if(s[i] == ' ') ++i;
            else if(s[i] >= '0' && s[i] <= '9')
            {
                int tmp = 0;
                while(i < s.size() && s[i] >= '0' && s[i] <= '9')
                tmp = tmp * 10 + (s[i++] - '0');
                if(op == '+') st.push_back(tmp);
                else if(op == '-') st.push_back(-tmp);
                else if(op == '*') st.back() *= tmp;
                else if(op == '/') st.back() /= tmp;
            }
            else
            {
                op = s[i];
                ++i;
            }
        }

        int ans = 0;
        for(auto& x : st) ans += x;
        return ans;
    }
};

代码解析:

题目描述是让我们实现一个计算器,只是一个小型得计算器因为只涉及加减乘除。

那么针对这道题来说,我得建议是将所有数字丢到栈里面,
1、如果数字前面得运算符是‘+’那就直接丢到栈里面。
2、如果数字前面的运算符是‘-’那就取相反数丢到栈里面。
3、如果数字前面的运算符是‘*’那就将栈顶元素乘等当前数字。
4、如果数字前面的运算符是‘/’那就将栈顶元素除等当前数字。

还要一种细节问题,我们的数字在字符串中会有连续的数字,那么这种情况我们也要考虑进去。

具体的做法就是,不断的往该数字后面走,走一次乘等10再加上自己,直到走到了一个运算符或者越界之后即可。

同理,在我们查找到元素为数字之后,我们最后的 i 就会在内部被我们移动到运算符上或者越界。

字符串解码

题目描述:

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

编码规则为: 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"

代码实现:

class Solution 
{
public:
    string decodeString(string s) 
    {
        stack<string> st_s;
        stack<int> st_i;
        st_s.push("");

        for(int i = 0; i < s.size();)
        {
            if(s[i] >= '0' && s[i] <= '9')
            {
                int tmp = 0;
                while(i < s.size() && s[i] >= '0' && s[i] <= '9')
                    tmp = tmp * 10 + (s[i++] - '0');
                st_i.push(tmp);    
            }
            else if(s[i] == '[')
            {
                ++i;
                string tmp = ""; // 一定要在这里创建空数组!
                while(i < s.size() && s[i] >= 'a' && s[i] <= 'z')
                    tmp += s[i++];
                st_s.push(tmp);
            }
            else if(s[i] == ']')
            {
                string tmp = st_s.top();
                int k = st_i.top();
                st_i.pop();
                st_s.pop();
                while(k--)
                    st_s.top() += tmp;
                ++i;
            }
            else if(s[i] >= 'a' && s[i] <= 'z')
            {
                st_s.top() += s[i++];
            }
        }
        return st_s.top();
    }
};

代码解析:

题目描述也是非常的简单啊,但是这个代码有点不好写,其实本质这些栈的题目都是围绕着模拟来展开的。现在就是你给我个2[ac],我就要给你变成acac。这就是题目的基本意思,但是会有一种情况,题目会给你这样的例子:2[ab2[2[cc]]最后转换就是abccccccccabcccccccc,所以他是会出嵌套的情况,而针对数字,也会有两位数以上的数字,那这里我们还要进行处理。

1、如果遍历到数字,按上题的方式找到两位数及以上入st_i栈。
2、如果遍历到字母,按上题的方式找到一个整个字符串,加在st_s栈顶元素字符串后。
3、如果遍历到’[‘,先++i,最重要的是要先创建一个空字符串tmp,然后凭借记录在tmp里,最后将后面的字符串找到,丢到st_s栈里。
4、如果遍历到’]',取出st_i栈顶元素,和st_s栈顶元素,分别以k和tmp记录下来,然后丢掉st_s栈顶元素,之后循环k次,给新的st_s栈顶元素 += tmp。

验证栈序列

题目描述:

给定 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 之前弹出。

代码实现:

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

代码解析:

题目描述我们也好理解,如果有尝试考研的同学肯定有做过这道题,简单来说,拿示例1来看,我们有一个栈,我可以先push1 2 3 4,然后把4给推出去,这样栈剩下就只有1 2 3,接下来想要推5出去,但我没有,所以我就加到5,加到了然后推出去。后面栈仍然是1 2 3,然后想要推出去的就是3 2 1,所以最终栈就是空的了。

相关文章:

  • [Lc滑动窗口_1] 长度最小的数组 | 无重复字符的最长子串 | 最大连续1的个数 III | 将 x 减到 0 的最小操作数
  • 蓝桥与力扣刷题(蓝桥 核桃的数量)
  • 研究生综合管理系统的开发与应用在农业大学中的实践
  • Redis详解(实战 + 面试)
  • C语言——文件操作
  • Hive-06之函数 聚合Cube、Rollup、窗口函数
  • 一、旋钮式滑动变阻器模块
  • 最新常见的图数据库对比,选型,架构,性能对比
  • LangPrompt提示词
  • 【弹性计算】弹性裸金属服务器和神龙虚拟化(三):弹性裸金属技术
  • 【RAG】Embeding 和 Rerank学习笔记
  • 【计算机网络入门】初学计算机网络(九)
  • jenv 使用指南
  • Java异常
  • Python Cookbook-2.24 在 Mac OSX平台上统计PDF文档的页数
  • [含文档+PPT+源码等]精品基于Python实现的微信小程序的乡村医疗咨询系统
  • Gin从入门到精通 (七)文件上传和下载
  • 计算机毕业设计SpringBoot+Vue.js社区智慧养老监护管理平台(源码+文档+PPT+讲解)
  • C++20中`constexpr`的显著增强
  • 前缀和算法 算法4
  • 音乐网站建设论文/深圳网站建设服务
  • 如何做快递api接口网站/平面设计网站
  • 东莞拓步网站建设/什么叫seo
  • 虚拟机 网站建设/疫情防控最新信息
  • 福州做网站互联网公司排名/武汉seo论坛
  • wordpress编辑菜单/淘宝seo软件