C++刷题(二):栈 + 队列

📝前言说明:

本专栏主要记录本人的基础算法学习以及刷题记录,使用语言为C++。

每道题我会给出LeetCode上的题号(如果有题号),题目,以及最后通过的代码。没有题号的题目大多来自牛客网。对于题目的讲解,主要是个人见解,如有不正确,欢迎指正,一起进步!

🎬个人简介:努力学习ing

📋本专栏:C++刷题专栏

📋其他专栏:C++学习笔记C语言入门基础python入门基础python刷题专栏

🎀CSDN主页 愚润泽

题目

  • [20. 有效的括号](#20. 有效的括号)
  • [225. 用队列实现栈](#225. 用队列实现栈)
  • [232. 用栈实现队列](#232. 用栈实现队列)
  • [622. 设计循环队列](#622. 设计循环队列)
  • [面试题03.05. 栈排序](#面试题03.05. 栈排序)

20. 有效的括号

经典的括号匹配题:利用栈。遇到左括号:入栈,遇到右括号:出栈

不过写代码时要注意:因为我们要让'(' 匹配 ')',所以遇到左括号时,直接将它对应的右括号入栈,后续可以直接字符比较判断。

cpp 复制代码
class Solution {
public:
    bool isValid(string s) {
        stack<char> st;
        for(auto ch : s)
        {
            if(ch == '('){
                st.push(')'); // 需要匹配的
            }
            else if (ch == '['){
                st.push(']');
            }
            else if (ch == '{'){
                st.push('}');
            }
            else{
                if( st.empty() || ch != st.top()){ // 这里要先判断栈是否为空
                    return false;
                }
                st.pop();
            }

        }
        return st.empty();
    }
};

225. 用队列实现栈

首先我们要了解栈的特点:先进后出,队列的特点:先进先出

因此,这道题的难点在于:如何让新入队的元素处于队头?

这道题给了我们两个队列,如果将一个队列当做主队列(即栈),另一个队列作为辅助队列,我们就可以利用辅助队列来改变新入队的元素的位置:

前提:每次操作前,辅助队列要为空。

思想:如果直接让新元素进主队列,那这个元素肯定是最后一个了,但是直接让新元素进辅助队列,那这个新元素就是辅助的第一个元素。所以我们先让新元素进入辅助队列,然后再把主队列(栈)里的元素依次出栈放入辅助队列,这样在辅助队列里新元素第一个出队列,而其他元素的出队列顺序与原来的主队列(栈)保持一致。这时候我们再交换辅助队列和主队列的身份。

cpp 复制代码
class MyStack {
public:
    queue<int> queue1; 
    queue<int> queue2; 
    MyStack() {
        
    }
    
    void push(int x) {
        queue2.push(x); // 把新元素放到辅助队列
        while(!queue1.empty()){
            queue2.push(queue1.front()); // 依次将栈的元素放入辅助队列
            queue1.pop();
        }
        swap(queue1, queue2);
    }
    
    int pop() {
        int r = queue1.front();
        queue1.pop();
        return r;
    }
    
    int top() {
        return queue1.front();
    }
    
    bool empty() {
        return queue1.empty();
    }
};

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */

232. 用栈实现队列

只需要让一个栈进,一个栈负责出就行了。当一个栈的元素全部倒入另一个栈,这时候元素的出入顺序就会完全改变一次。(为了节约时间,我们只在outStack里面元素彻底为空且遇到出栈需求时,才将inStack的数据倒入`outStack)

cpp 复制代码
class MyQueue {
public:

    stack<int> inStack, outStack;

    void in_to_out(){ // 倒转
        while(!inStack.empty()){
            outStack.push(inStack.top());
            inStack.pop();
        }
    }

    MyQueue() {
        
    }
    
    void push(int x) {
        inStack.push(x);
    }
    
    int pop() {
        if(outStack.empty()){
            in_to_out();
        }
        int r = outStack.top();
        outStack.pop(); 
        return r;
    }
    
    int peek() {
        if(outStack.empty()){
            in_to_out();
        }
        return outStack.top();
    }
    
    bool empty() {
        return inStack.empty() && outStack.empty();
    }
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */

622. 设计循环队列

下面解法以数组为例:

环形队列的关键在于:1,如何通过取模来达到走环的效果;2,如何判断队列满和空的情况。

对于循环:当一个数+1时可能超出最大值,则需要%来控制此数的大小任然在下标范围内;

对于判空:起始时front指针和rear指针都指向空;对于满,我们可以牺牲一个空间,即:当rear+1 == front的时候为满(但注意rear + 1要确保在数组下标内)。

下面做法以front的后一位为第一个数据位为例:

cpp 复制代码
class MyCircularQueue {
public:

    // 用数组来模拟循环队列,让front指向的位置为空,front下一个位置才有节点
    // front == rear时为空,当 rear + 1 == front 时为满 
    MyCircularQueue(int k) 
    {
        capacity = k;
        front = rear = 0;
        que = vector<int> (k+1); // 比容量多开一个空间,则数组下标为[0, k](后续我们要让rear和front的下标在这个范围内,不然会越界)
    }
    
    bool enQueue(int value) {
        if(isFull()){
            return false;
        }
        rear = (rear + 1) % (capacity + 1);  
        que[rear] = value;
        return true;
    }
    
    bool deQueue() {
        if(isEmpty()){
            return false;
        }
        front = (front + 1) % (capacity + 1);
        return true;
    }
    
    int Front() {
        if(isEmpty()){
            return -1;
        }
        return que[(front + 1) % (capacity + 1)];
    }
    
    int Rear() {
        if(isEmpty()){
            return -1;
        }
        return que[rear];
    }
    
    bool isEmpty() {
        return rear == front;
    }
    
    bool isFull() {
        return ((rear + 1) % (capacity + 1)) == front;
    }

private:
    int front;
    int rear;
    int capacity;
    vector<int> que;
};

/**
 * Your MyCircularQueue object will be instantiated and called as such:
 * MyCircularQueue* obj = new MyCircularQueue(k);
 * bool param_1 = obj->enQueue(value);
 * bool param_2 = obj->deQueue();
 * int param_3 = obj->Front();
 * int param_4 = obj->Rear();
 * bool param_5 = obj->isEmpty();
 * bool param_6 = obj->isFull();
 */

面试题03.05. 栈排序

这道题的题目表述不清楚,看示例可以发现,实际上是往栈里面插入元素,要保证插入后的顺序从栈底到栈顶是从大到小的。

我们只需要将每次要插入的元素和栈中已经有的元素作比较,找到合适的位置插入。

如:栈顶元素为t,要插入元素为val,如果val < t,就直接入栈,否则,先让t进入辅助栈,重复此过程,直到找到合适的位置插入,插入完后,把st2的元素倒回来。

cpp 复制代码
class SortedStack {
public:
    SortedStack() {
        
    }
    
    void push(int val) {
        while( !st1.empty() && st1.top() < val){
            st2.push(st1.top()); // 把st1的元素暂存到st2
            st1.pop();
        }
        st1.push(val);
        // 把st2的元素倒回来
        while(!st2.empty()){
            st1.push(st2.top());
            st2.pop();
        }
        

    }
    
    void pop() {
        if(!st1.empty()){
            st1.pop();
        }
    }
    
    int peek() {
        if(!st1.empty()){
            return st1.top();
        }
        return -1;
    }
    
    bool isEmpty() {
        return st1.empty();
    }
private:
    stack<int> st1, st2;
};

/**
 * Your SortedStack object will be instantiated and called as such:
 * SortedStack* obj = new SortedStack();
 * obj->push(val);
 * obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->isEmpty();
 */

🌈我的分享也就到此结束啦🌈

要是我的分享也能对你的学习起到帮助,那简直是太酷啦!

若有不足,还请大家多多指正,我们一起学习交流!

📢公主,王子:点赞👍→收藏⭐→关注🔍

感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

相关推荐
爱编程的小赵8 分钟前
第十五届蓝桥杯C/C++B组拔河问题详解
c语言·c++·蓝桥杯
奋进的小暄1 小时前
贪心算法(7)(java) 分发饼干
数据结构·算法·贪心算法
无名之逆1 小时前
Hyperlane:Rust 生态中的轻量级高性能 HTTP 服务器库,助力现代 Web 开发
服务器·开发语言·前端·后端·http·面试·rust
江沉晚呤时1 小时前
使用 .NET Core 实现 RabbitMQ 消息队列的详细教程
开发语言·后端·c#·.netcore
大模型铲屎官1 小时前
从零精通机器学习:线性回归入门
开发语言·人工智能·python·算法·机器学习·回归·线性回归
试剂界的爱马仕2 小时前
投资早报 3.14
人工智能·深度学习·算法·机器学习·区块链·ai写作
搞不懂语言的程序员2 小时前
单例模式详解(java)
java·开发语言·单例模式
WangMing_X2 小时前
C#实现图像缩放与裁剪工具
开发语言·c#·图像
ksbglllllll2 小时前
ccf3401矩阵重塑(其一)
c++·算法·矩阵
Python破壁人手记2 小时前
《我的Python觉醒之路》之转型Python(十五)——控制流
java·服务器·开发语言·网络·python