【算法系列】栈

news2024/11/20 8:24:51

目录

leetcode题目

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

二、比较含退格的字符串

三、基本计算器 II

四、字符串解码

五、验证栈序列

六、有效的括号

七、最小栈

八、逆波兰表达式求值

九、用栈实现队列

十、用队列实现栈


leetcode题目

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

1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/1.题目解析

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

2.算法分析

显然该题是要用栈,遍历字符串,当遍历到的元素和栈顶元素一样时,就让栈顶元素出栈,否则就让遍历到的元素入栈;本题如果创建一个栈,最后还要把栈的元素都依次插入到字符串中,还得逆序字符串,因此我们直接用字符串模拟栈~

3.算法代码

class Solution {
public:
    string removeDuplicates(string s) 
    {
        string ret; //模拟栈
        for(auto ch : s)
        {
            if(ret.size() && ch == ret.back()) ret.pop_back();
            else ret.push_back(ch);
        }
        return ret;
    }
};

二、比较含退格的字符串

844. 比较含退格的字符串 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/backspace-string-compare/1.题目解析

本质和题目一是一样的

2.算法分析

依旧是用字符串模拟栈,解法和题目是一样的~

3.算法代码

class Solution {
public:
    bool backspaceCompare(string s, string t) 
    {
        return changeStr(s) == changeStr(t);
    }

    string changeStr(string& s)
    {
        string ret;
        for(char ch : s)
        {
            if(ch != '#') ret += ch;
            else 
            {
                if(ret.size())
                    ret.pop_back(); 
            }
        }
        return ret;
    }
};

三、基本计算器 II

227. 基本计算器 II - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/basic-calculator-ii/1.题目解析

给定一个字符串(包含加减乘除运算), 字符串中可能有空格,求最终结果

2.算法分析

利用栈来模拟计算过程(栈+变量op)

大家可以根据下面的总结去分析一下这个例子: 4-3+6*4/2-123+34

1.遇到操作符, 更新操作符 op (开始置成'+')

2.遇到数字:

2.1 先把数字提取出来 tmp

2.2 分情况讨论,根据op的符号:

     2.2.1 op == '+',  tmp入栈

     2.2.2 op == '-',  -tmp入栈

     2.2.3 op == '*', 直接乘到栈顶元素上

     2.2.4 op == '/', 直接除到栈顶元素上

最后把栈中的所有元素加起来就可以了~

3.算法代码

class Solution {
public:
    int calculate(string s)
    {
        vector<int> st; //数组模拟栈
        int i = 0, n = s.size();
        char op = '+';
        while(i < n)
        {
            if(s[i] == ' ') i++; //跳过空格
            else 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');
                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++];
        }
        //将栈中的所有元素加起来,就是最终结果
        int ret = 0;
        for(auto x : st)
            ret += x;
        return ret;
    }
};

四、字符串解码

394. 字符串解码 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/decode-string/description/1.题目解析

k[encoded_string], 表示将encoded_string重复k次,给定的字符串中可能有多个[ ], 求最终解码后字符串

2.算法分析

用双栈模拟字符串解码过程  大家可以用下面的方法去分析一下这个例子:

eg:  1 [ a 2 [ b c ] ] d e 3 [ f ]

注意:字符串栈开始放一个空字符串,就是为了 防止 放到"字符串栈"栈顶的字符串后面时栈为空而非法访问报错~

1.遇到数字:把数字提取出来, 放入"数字栈"

2.遇到 '[':把后面的字符串提取出来,放入"字符串栈"中

3.遇到 ']':  取出两栈的栈顶元素进行解析,然后放到"字符串栈"栈顶的字符串后面

4.遇到单独的字符:提取出字符串,直接放到"字符串栈"栈顶的字符串后面

遍历完题目所给字符串后,字符串栈的栈顶字符串就是最终解码结果~

3.算法代码

class Solution {
public:
    string decodeString(string s) 
    {
        stack<int> nums;
        stack<string> st;
        st.push(""); //字符串开始放一个空串
        int i = 0, n = s.size();
        while(i < n)
        {
            if(s[i] >= '0' && s[i] <= '9') //遇到数字,提取数字,放入数字栈
            {
                int tmp = 0;
                while(s[i] >= '0' && s[i] <= '9')
                    tmp = tmp * 10 + (s[i++] - '0');
                nums.push(tmp);
            }
            else if(s[i] == '[') //遇到'[', 将'['后面的字符串提取出来,放入字符串栈
            {
                i++;
                string tmp;
                while(s[i] >= 'a' && s[i] <= 'z')
                    tmp += s[i++];
                st.push(tmp);
            }
            else if(s[i] == ']') //遇到']', 取出两栈的栈顶元素,进行解析,然后将结果加入到字符串栈栈顶字符串的后面
            {
                string tmp = st.top();
                st.pop();
                int k = nums.top();
                nums.pop();
                while(k--)
                    st.top() += tmp;
                i++; //跳过']'
            }
            else //遇到单独的字符串,直接提取字符串,加入到字符串栈栈顶元素的后面
            {
                string tmp;
                while(i < n && s[i] >= 'a' && s[i] <= 'z')
                    tmp += s[i++];
                st.top() += tmp;
            }
        }
        return st.top();
    }
};

五、验证栈序列

946. 验证栈序列 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/validate-stack-sequences/description/栈的压入、弹出序列_牛客题霸_牛客网 (nowcoder.com)icon-default.png?t=N7T8https://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106?tpId=13&&tqId=11174&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking1.题目解析

给定入栈序列,判断给定的出栈序列是否成立

2.算法分析

借助栈模拟过程即可

1.让pushed元素一直进栈

2.定义i下标遍历popped数组,进栈后判断栈顶元素是否和popped[i] 相等,相等就出栈, 同时i++

所有元素进栈完毕之后,判断 i 是否已经遍历完毕,或者判断栈是否为空即可

3.算法代码

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) 
    {
        stack<int> st;
        int i = 0;
        for(auto x : pushed) 
        {
            st.push(x); //让pushed中的元素一直进栈
            while(st.size() && st.top() == popped[i]) //判断栈顶元素与popped对应位置元素是否相等
            {
                st.pop();
                i++;
            }
        }
        //return st.empty(); 
        return i == popped.size();
    }
};

六、有效的括号

20. 有效的括号 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/valid-parentheses/1.题目解析

给定一个包含三类括号的字符串,判断括号是否有效匹配

2.算法分析

用栈模拟括号匹配过程即可

1.遇到左括号,入栈

2.遇到右括号,取栈顶元素和右括号匹配,匹配失败就返回false(注意细节问题,就是当第一个字符就是右括号,栈中还没有元素,取栈顶元素会非法访问,要特殊处理一下)

当遍历完整个字符串之后,如果栈中还有元素,就返回false, 否则返回true

3.算法代码

class Solution {
public:
    bool isValid(string s) 
    {
        int i = 0, n = s.size();
        stack<char> st;
        while(i < n)
        {
            if(s[i] == '(' || s[i] == '{' || s[i] == '[') //左括号就进栈
                st.push(s[i]);
            else //是右括号就取栈顶元素
            {
                //1.开始就是右括号, 返回false
                if(st.empty()) 
                    return false;
                //2.判断括号是否匹配
                char ch = st.top();
                st.pop();
                if(ch == '(' && s[i] != ')'
                || ch == '{' && s[i] != '}'
                || ch == '[' && s[i] != ']')
                    return false;
            }
            i++;
        }
        return st.empty(); //如果栈中还有元素,就返回false
    }
};

七、最小栈

155. 最小栈 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/min-stack/description/1.题目解析

设计一个栈,支持栈的常规操作,并且能够在常数时间内检索到栈中的最小元素

2.算法分析

借助一个栈 _minst, _minst的栈顶元素保存了栈  _st 中的最小值

push: 当_minst为空 或 插入元素val <= _minst的栈顶元素时候,val插入_minst

pop: 当_st的栈顶元素 == _minst的栈顶元素时,弹出 _minst的栈顶元素

3.算法代码

class MinStack {
public:
    MinStack() {}
    
    void push(int val) {
        _st.push(val);
        if(_minst.empty() || val <= _minst.top())
        {
            _minst.push(val);
        }
    }
    
    void pop() {
        if(_st.top() == _minst.top())
        {
            _minst.pop();
        }
        _st.pop(); 
    }
    
    int top() {
        return _st.top();
    }
    
    int getMin() {
        return _minst.top();
    }

    stack<int> _st;
    stack<int> _minst;
};

八、逆波兰表达式求值

150. 逆波兰表达式求值 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/evaluate-reverse-polish-notation/1.题目解析

给定一个逆波兰表达式(后缀表达式), 求表达式的值

2.算法分析

逆波兰表达式(后缀表达式),该表达式可以很好的借助栈来模拟计算

1. 遇到数字,入栈

2. 遇到操作符,取出栈顶的两个元素,分别作为右操作数和左操作数,进行计算, 计算结果放入栈中

3.算法代码

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for(auto& str : tokens)
        {
            if(str == "+"
            || str == "-"
            || str == "*"
            || str == "/")
            {
                int right = st.top();
                st.pop();
                int left = st.top();
                st.pop();
                switch(str[0])
                {
                    case '+':
                        st.push(left + right);
                        break;
                    case '-':
                        st.push(left - right);
                        break;
                    case '*':
                        st.push(left * right);
                        break;
                    case '/':
                        st.push(left / right);
                        break;  
                }
            }
            else
            {
                st.push(stoi(str));
            }
        }
        return st.top();
    }
};

九、用栈实现队列

232. 用栈实现队列 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/implement-queue-using-stacks/1.题目解析

用两个栈实现队列

2.算法分析

定义两个栈,pushst用于压入元素,popst用于弹出元素~

3.算法代码

class MyQueue {
public:
    MyQueue() {}
    
    void push(int x)
    {
        pushst.push(x);
    }
    
    int pop() 
    {
        int top = peek();
        popst.pop();
        return top;
    }
    
    int peek() 
    {
        if(popst.empty())
        {
            while(!pushst.empty())
            {
                int top = pushst.top();
                pushst.pop();
                popst.push(top);
            }
        }
        return popst.top(); 
    }
    
    bool empty() 
    {
        return popst.empty() && pushst.empty();
    }
private:
    stack<int> pushst;
    stack<int> popst;
};


十、用队列实现栈

225. 用队列实现栈 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/implement-stack-using-queues/description/1.题目解析

用两个队列实现栈

2.算法分析

两个队列,使用时保持一个队列为空,一个队列不为空

push: 哪个队列不为空,push到哪个队列

pop: 哪个队列不为空,哪个队列就一直pop元素到另外一个队列,直到原本不为空的队列只剩下一个元素,返回该元素并从队列中pop即可

top: 哪个队列不为空,就返回哪个队列的back()

empty: 当栈中有元素时始终有1个队列为空,1个不为空,只有两队列都为空时,栈才为空

3.算法代码

class MyStack {
public:
    MyStack() {}
    
    void push(int x)
    {
        if(!q1.empty())
            q1.push(x);
        else 
            q2.push(x);
    }
    
    int pop() 
    {
        if(!q1.empty())
        {
            while(q1.size() > 1)
            {
                q2.push(q1.front());
                q1.pop();
            }
            int top = q1.front();
            q1.pop();
            return top;
        }
        else
        {
            while(q2.size() > 1)
            {
                q1.push(q2.front());
                q2.pop();
            }
            int top = q2.front();
            q2.pop();
            return top;  
        }
    }
    
    int top() 
    {
        if(!q1.empty())
            return q1.back();
        else 
            return q2.back();
    }
    
    bool empty() 
    {
        return q1.empty() && q2.empty();
    }
private:
    queue<int> q1;
    queue<int> q2;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1657171.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mybatis存储数据将数据转为json

第一种方法 先创建一个表类型如下 创建一个项目&#xff0c;写一个接口 &#xff0c; 写一个JsonTypeHandler类继承BaseTypeHandler public class JsonTypeHandler<T> extends BaseTypeHandler<T> {private Class<T> clazz;//构造函数 --- >接收一个 Cl…

在数据分析中所需要运用到的概率论知识

数据分析 前言一、总体二、样本三、统计抽样抽取的基本准则 四、随机抽样抽签法随机数法 五、分层抽样六、整群抽样七、系统抽样八、统计参数常用的分布函数参数 九、样本统计量十、样本均值和样本方差十一、描述样本集中位置的统计量样本均值样本中位数样本众数 十二、描述样本…

计算机发展史故事【5】

电脑创世纪 全世界在隆隆的炮火声中迎来了1943 年。硝烟密布&#xff0c;战鼓催春&#xff0c;战争的迫切需要&#xff0c;像一只有力的巨手&#xff0c;为电脑的诞生扫清障碍&#xff0c;铺平道路。 4 月9 日&#xff0c;美国马里兰州阿贝丁&#xff0c;陆军军械部召集的一次会…

深度学习论文代码研读系列(1)Transformer:Attention Is All You Need

目录 摘要 1 引言 2背景 3模型架构 3.1编码器和解码器堆栈编码器&#xff1a; 3.2 Attention 3.2.1 Scaled Dot-Product Attention 3.2.2多头注意力 3.2.3注意力在我们的模型中的应用 3.3位置前馈网络 3.4嵌入和Softmax 3.5位置编码 4为什么自注意力 5 Training 6…

小红书释放被封手机号 无限注册

前几年抖音也可以释放被封手机号 那时候都不重视 导致现在被封手机号想释放 基本不可能的 或者就是最少几百块 有专业的人帮你通过某些信息差释放 本教程是拆解 小红书被封手机号怎么释放&#xff0c;从今年开始&#xff0c;被封的手机号无法注销了 所以很困扰 那么本教程来…

AI绘画Stable Diffusion 插件篇:智能标签提示词插件sd-danbooru-tags-upsampler

大家好&#xff0c;我是向阳。 关于智能标签提示词插件&#xff0c;在很早之前就介绍过很多款了&#xff0c;今天再给大家介绍一款智能标签提示词插件sd-danbooru-tags-upsampler。该智能提示词插件是今年2月23号才发布的第一版V0.1.0&#xff0c;算是比较新的智能提示词插件。…

Semi-decentralized Federated Ego Graph Learning for Recommendation

论文概况 本文是2023年WWW的一篇联邦推荐论文&#xff0c;提出了一个半去中心化的联合自我图学习框架。 Introduction 作者提出问题 现有的推荐方法收集所有用户的自我图来组成一个全局图&#xff0c;导致隐私风险。联合推荐系统已被提出来缓解隐私问题&#xff0c;但在客户…

【半夜学习MySQL】数据库概念详解探索数据库到底是如何存储的?

&#x1f3e0;关于专栏&#xff1a;半夜学习MySQL专栏用于记录MySQL数据相关内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 什么是数据库主流数据库与数据库分类数据库的基本使用数据库的启动及关闭查看配置文件与数据库存储位置连接数据库服务器服务…

Linux进程——Linux环境变量

前言&#xff1a;在结束完上一篇的命令行参数时&#xff0c;我们简单的了解了一下Linux中的环境变量PATH&#xff0c;而环境变量不只有PATH&#xff0c;关于更多环境变量的知识我们将在本篇展开&#xff01; 本篇主要内容&#xff1a; 常见的环境变量 获取环境变量的三种方式 本…

[性能优化] ScrollView视图优化为循环列表

问题描述&#xff1a; 原先商城的物品栏中的item 是load在一个scrollView 下&#xff0c;用于滑动查看。仅仅在父级panel下是使用了NGUI原生的scrollview 组件&#xff0c;随着商场物品列表中新物品的增多。panel下加载的实例也非常庞大。而大部分的实例用户也无法看到&#x…

YOLOv5,YOLOv7改进之结合​SOCA

1.SOCA moudle结构图 2,YOLOv5,YOLOv7改进之结合​SOCA 1.配置common.py文件 #SOCA moudle 单幅图像超分辨率 class Covpool(Function):@staticmethoddef forward(ctx, input):x = inputbatchSize = x.data.shape[0]dim = x.data.shape[1]h = x.data.shape[2]w = x.data.sha…

上位机图像处理和嵌入式模块部署(树莓派4b和c++新版本的问题)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 自己读书的时候是03年&#xff0c;学习c也是差不多04年开始&#xff0c;到现在基本上20年了。这20年过程当中&#xff0c;其实c的语言版本一直是在…

队列 (Queue)

今日励志语句&#xff1a;别总听悲伤的歌&#xff0c;别总想从前的事&#xff0c;别让过去拖住脚&#xff0c;别让未来被辜负。 前言&#xff1a;前面写了一篇 栈的实现&#xff0c;接下来学习一下它的"兄弟" 一、队列的概念&#xff1a; 队列&#xff1a; 也是数据…

nginx代理原理(端口复用)探究

前言&#xff1a;对于一些常用的插件&#xff0c;我们应该学会如何使用。同时&#xff0c;其实现原理也要进行深究&#xff0c;可以为其他的项目开发做借鉴。 探究方案&#xff1a; 一、发布两个不同的服务&#xff0c;这两个服务的端口不致 二、配置nginx&#xff0c;让这两…

JavaScript百炼成仙自学笔记——13

函数七重关之六&#xff08;“new”一个函数&#xff09; 看个代码&#xff1a; function hello(){console.log(this); } 1、this&#xff1a;也是JavaScript中的一个关键字&#xff0c;永远指向当前函数的调用者 解释一下,有两层意思&#xff1a; ①this要嘛不出现&#…

从心理学角度看,GPT 对人有什么影响?

开启个性化AI体验&#xff1a;深入了解GPT的无限可能 导言 GPT 与我们日常生活的融合标志着技术进步的重大飞跃&#xff0c;为提高效率和创新提供了前所未有的机遇。然而&#xff0c;当我们与这些智能系统日益紧密地交织在一起时&#xff0c;探索它们对个人产生的细微的心理影响…

康姿百德集团公司官网价格统一,产品编码可查真伪售后有保障

康姿百德床垫&#xff0c;静音设计让你享受安静睡眠环境 随着越来越多的人睡眠质量差&#xff0c;夜间难以入睡&#xff0c;人们开始意识到睡眠问题已经不仅仅是健康问题&#xff0c;更上升为一种社会问题&#xff0c;急需得到解决。作为寝具行业中的优质品牌&#xff0c;康姿…

【Linux】如何定位客户端程序的问题

文章目录 1 客户端程序和服务端程序的差别2 问题类型2.1 崩溃(crash)2.2 CPU高2.3 内存高2.4 线程卡死 3 总结 1 客户端程序和服务端程序的差别 客户端程序是运行在终端上&#xff0c;通常都会与业务系统共存&#xff0c;而服务端程序通常会运行在单独的节点上&#xff0c;或者…

Leetcode—394. 字符串解码【中等】

2024每日刷题&#xff08;131&#xff09; Leetcode—394. 字符串解码 实现代码 class Solution { public:string decodeString(string s) {string curstr;int curNum 0;stack<pair<string, int>> st; for(char c: s) {if(isdigit(c)) {curNum curNum * 10 (c…