代码随想录|栈与队列

目录

一:基础回忆

二:题目

                  1.用栈实现队列

2.用队列实现栈

3.有效的括号(栈)

4.删除字符串种所有相邻重复项(栈)

5.前k个高频元素(综合)

6.逆波兰表达式求值


一:基础回忆

        栈  先进后出  

                进栈(栈的插入)push                  出栈(栈的删除)pop           

                top栈顶:允许插入和删除的一端        栈底bottom         空栈

        队列   先进先出

                队头front:队首 允许删除的一端                队尾rear                  空队列4

                top  back push pop empty front 

二:题目

        1.用栈实现队列

                这里用栈来模拟队列只用一个栈是不行,要两个,一个进栈,一个出栈

一个栈为题目开始的队列所以第一个问就是将元素放入到栈中,并以个栈是辅助栈

实现 MyQueue 类:

push(x) -- 将一个元素放入队列的尾部。
pop() -- 从队列首部移除并返回元素。
peek() -- 返回队列首部的元素。
empty() -- 返回队列是否为空。

class MyQueue{
public:
        stack<int> stIn;
        stack<int> stOut;//定义

        MyQueue(){
        
        }
        void push(int x){
                stIn.push(x);//加入一个元素
        }

        int pop(){
            if(stOut.empty()){
                //从stIn导入的数据直到stIn为空
                while(!stIn.empty()){
                        stOut.push(stIn.top());//将进栈中的第一个元素加入到出栈
                        stIn.pop();//把进来栈的全部数都pop
                                     }
                              }
            int result = stOut.top();//获取第一个元素
            stOut.pop();//把第一个元素弹出
            return result;
                }

        //取队列的第一个元素
        int peek(){
                int res=this->pop();//直接调用上面的pop函数,调用类,在pop函数中弹出了,所以需要把他加进去
                stOut.push(res);//添加回去res函数
                return res;
        }

        bool empty(){
                return stIn.empty()&&stOut.empty();
        }
};

2.用队列实现栈

        

  • push(x) -- 元素 x 入栈
  • pop() -- 移除并返回栈顶元素
  • top() -- 获取栈顶元素
  • empty() -- 返回栈是否为空

若是用栈实现该题,就是很简单

class Solution{
public:
        stack<int> st;

        void push(x){
                st.push(x);
        }

        int pop(){
          int  res = st.top();
          st.pop(res);
          return res;
        
        int top(){
            return st.top();
        }
        
        bool empty(){
            return st.empty();
        }

            

两个队列模拟栈

class MyStack{
public:
        queue<int> que1;
        queue<int> que2;//辅助队列,用来备份
        
        MyStack(){
        }

        void push(int x){
            que1.push(x);
        }

        int pop(){
                int size = que.size();
                size--;
                while(size--){//将que1导入que2,但要留下最后一个元素
                    que2.push(que1.front());//注意队列 front  栈 top
                    que1.pop();
                }

                int result = que1.front();//留下的最后一个元素就是要返回的值
                que1.pop();
                que1=que2;       //赋值
                while(!que2.empty()){  //一定要清空que2
                        que2.pop();
                    }
                return result;
            }

        int top(){
                return que1.back()l
        }

        bool empty(){
                return que1.empty();
        }
};

只用一个队列

class MyStack{
public:
        queue<int> que;//定义
        MyStack(){

        }

        void push(int x){
                que.push(x);//push(x) -- 元素 x 入栈
        }

        int pop(){//pop() -- 移除栈顶元素
                int size=que.size();
                size--;
                while(size--){//从队列头部开始(除最后一个元素)
                    que.push(que.front());
                    que.pop;
                }
                int result=que.front();//此时的顺序就是栈的顺序
                que.pop();
                return result;
            }
        
        int top(){//top() -- 获取栈顶元素
            return que.back();
        }

        bool empty(){//empty() -- 返回栈是否为空
                return que.empty();
        }
};

3.有效的括号(栈)

给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。(这里就需要讨论见分析问题)
  • 左括号必须以正确的顺序闭合。
  • 注意空字符串可被认为是有效字符串。

 代码中st.top==s[i]  已经包含了上面的两种情况(左和右匹配,左正确的顺序闭合)

由于于栈的结构特殊性,非常适合做对称匹配类的题目---------思考计算机的运行方式(自动补充括号)

分析问题:  (1)括号多余:左边多余  右边多余

                    (2)括号不匹配

匹配度从中间断开,左右匹配,从栈顶开始所以用栈

class Solution{
public:
    bool isValid(string s){
        if(s.size()%2!=0)return false;
//开括号的长度是否匹配,若为奇数,则一定多余或少了
        stack<char> st;//定义栈
        for(int i=0;i<s.size();i++){
            if(s[i]=='(')st.push(')');
            else if(s[i]=='{')st.push('}');
            else if(s[i]=='[')st.push(']');
//确认有哪些符号,并将对应的符号转换为右括号进栈
            else if(st.empty()||st.top()!=s[i])  return false;
//栈里为空或者栈没有匹配的字符  则是错误的
            else st.pop();//  st.top==s[i]  ,弹出元素,此时在匹配右括号(消消乐)
        }
//前面的for判断栈已经空了
           return st.empty();//empty==false
//遍历完所有的字符串,可是栈不为空,说明有相应的左括号与右括号不匹配  return   false  
//否则是true
    }
};

有几个问题:为什么if else条件那么多,且都要放在一个for里,感觉想不到,害怕条件筛选错误

为什么没有返回true

4.删除字符串种所有相邻重复项(栈)

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

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

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

示例:

  • 输入:"abbaca"
  • 输出:"ca"

分析:存放遍历过后的元素,方便遍历当前元素时看是不是相邻相同的字母,若是就pop(消消乐)

class Solution{
public:
    string removeDuplicates(string S){
        stack<char> st;
        for(char s:S){
            if(st.empty()||s!=st.top()) st.push(s);
//这里一定要考虑空就像是考虑是否=0一样(=第一个数)
//保证前一个与后一个是否相同(>=2个数)易忽略
            else st.pop();//s==st.top()
        }
        string result="";//定义新字符串
        while(!st.empty()){//把栈中的元素放到字符串result中
                result+=st.top();//记录到字符串
                st.pop();//弹出
        }
        reverse(result.begin(),result.end());//调用函数反转
        return result;
    }
};

问题:   为什么这个地方可以直接在栈内相加  且定义字符串的方法很新。 

若是直接用字符串做栈,省去了栈转化为字符串的操作(但不建议,这里主要是巩固栈,,详情见网站代码随想录)

5.前k个高频元素(综合)

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

示例 1:

  • 输入: nums = [1,1,1,2,2,3], k = 2
  • 输出: [1,2]

示例 2:

  • 输入: nums = [1], k = 1
  • 输出: [1]

分析:统计元素的出现概率(map)    对概率进行排序(优先级队列)   找到前k个高频元素(大顶堆取最上面的k个  ××,应该用小顶堆,统计最大的前k个)->这个问题需要去深入的学习几种建对的应用,筛选出来最好的

出现的专业名词:优先级队列  快排  map  大顶堆  小顶堆

详细代码见网站代码随想录 前k个高频元素

6.逆波兰表达式求值

输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

这个思考方式就很计算机  因为中缀运算(4+9/3)对于计算机不可能从左到右先运算9/3 后再倒回去,所以逆波兰可以实现

知识点stoll

        1.stol  将字符串转化为long int

        2.stoll  将字符串转化为long long int       字符串->整型

 字符串string是“    ”代表字符串中的值,字符char类型用‘    ‘   表示

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        // 力扣修改了后台测试数据,需要用longlong   
        stack<long long> st; 
        for (int i = 0; i < tokens.size(); i++) {
            if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {
                long long num1 = st.top();
                st.pop();
                long long num2 = st.top();
                st.pop();
                if (tokens[i] == "+") st.push(num2 + num1);
                if (tokens[i] == "-") st.push(num2 - num1);
                if (tokens[i] == "*") st.push(num2 * num1);
                if (tokens[i] == "/") st.push(num2 / num1);
            } else {
                st.push(stoll(tokens[i]));
            }
        }

        int result = st.top();
        st.pop(); // 把栈里最后一个元素弹出(其实不弹出也没事)
        return result;
    }
};

问题:我没看到题目说要用longlong 的文字表述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值