1. <tag-队列和栈(典型题)>-lt.622-循环队列 + lt.155-最小栈 + lt.232/剑指.09-栈模拟队列 + lt.225-队列模拟栈

lt.622-循环队列

[案例需求]
在这里插入图片描述
[思路分析]

  • 详细分析查看文章: 点我

[代码实现]

class MyCircularQueue {

    int rear = 0;
    int front = 0;
    int maxSize = 0;;
    int[] arr = {};
    public MyCircularQueue(int k) {
        //初始化队列长度
        this.maxSize = k + 1; //maxSize比k大1, 要留出一个空位作为判满的标志
        arr = new int[maxSize];
    }
    
    //入队. rear
    public boolean enQueue(int value) {
        //入队先判满
        if(this.isFull())return false;

        arr[rear] = value;
        rear = (rear + 1) % maxSize;
        return true;
    }
    
    //出队先判空
    public boolean deQueue() {
        if(this.isEmpty())return false;

        int data = arr[front];
        front = (front + 1) % maxSize;
        return true;
    }
    
    public int Front() {
        if(this.isEmpty())return -1;
        return arr[front % maxSize];
    }
    
    public int Rear() {
         if(this.isEmpty())return -1;

        return arr[(rear - 1 + maxSize) % maxSize];
    }
    
    public boolean isEmpty() {
        //判空
        if(rear == front) return true;
        return false;
    }
    
    public boolean isFull() {
        if((rear + 1) % maxSize == front) return true;
        return false;
    }
}

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

在这里插入图片描述

lt.155-最小栈(同剑指.30)

[案例需求]
在这里插入图片描述

[思路分析]

  • 最小栈, 根据题意, 往主栈中push了一堆元素, 同时不定期的pop出元素, 能够动态的返回某一时间点下的主栈中的最小值;
  • 稍加思考, 我们需要一个辅助栈, 记录主栈某次操作后主栈中的最小值;
  • 如何记录? 当然是在主栈入栈和出栈时, 把这个出栈或入栈的元素辅助栈的栈顶元素进行比较
    • 辅助栈, 我们也可称之为最小栈(存储每次主栈操作后, 栈中的最小值)
      1. 主栈入栈一个元素时, 辅助栈为空, 无条件入栈这个元素
      1. 主栈入栈一个元素时, 入栈元素 <= 辅助栈栈顶元素, 主栈入栈, 辅助栈也入栈;
      1. 主栈出栈一个元素时, 出栈元素 == 辅助站栈顶元素, 主栈出栈, 辅助栈也出栈;
        [代码实现]
class MinStack {

    //设计两个栈. 一个栈存储所有元素, 另一个最小栈存储每个出栈入栈状态下的最小值
    Stack<Integer> stack;
    Stack<Integer> minStack;

    public MinStack() {
        stack = new Stack<Integer>();
        minStack = new Stack<Integer>();
    }
    
    public void push(int val) {
        //入栈, 对于最小栈, 
        //栈为空时, 入栈, 
        //栈顶元素 >= 入栈元素时, 也要入栈
        if(minStack.size() == 0 || minStack.peek() >= val)minStack.push(val);
        stack.push(val);
    }
    
    public void pop() {
        //出栈, 对于最小栈
        //1. 出现元素 == 栈顶元素, 也出栈
        // if(stack.pop() == minStack.peek())minStack.pop();
         if(stack.pop().equals(minStack.peek()))minStack.pop();
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int getMin() {
        return minStack.peek();
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(val);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */

在这里插入图片描述

lt.232 / 剑指.09-栈模拟队列

[案例需求]
在这里插入图片描述在这里插入图片描述

[思路分析]
- 一个栈模拟队列,一个栈辅助
- 将一个栈当作输入栈,用于压入 push 传入的数据, 我们可以称之为辅助栈, 是主栈元素的一个中转站;
- 另一个栈当作输出栈,用于pop 和 peek 操作, 我们可以叫主栈, 主栈为空时, 辅助栈才能出栈到主栈

每次 pop 或 peek时,若输出栈为空则将输入栈的全部数据依次弹出并压入输出栈,这样输出栈从栈顶往栈底的顺序就是队列从队首往队尾的顺序。

[代码实现]

class MyQueue {

    //双栈模拟队列
    /**
        新元素入栈,先放入到辅助栈, 主栈为空的话, 辅助栈全部pop到主栈
        主栈不为空, 那就等待辅助栈为空时再全部pop到主栈.
		
		出栈时, 只需盯着主栈输出, 主栈没有元素了, 辅助栈出栈到主栈后继续出栈
        简单来说就是主栈负责输出, 辅助栈负责输入
     */

    Stack<Integer> stack1;//主栈, 输出
    Stack<Integer> stack2;//辅助栈. 输入

    public MyQueue() {
        stack1 = new Stack<>();
        stack2 = new Stack<>();
    }
    
    public void push(int x) {
        stack2.push(x);
    }
    
    public int pop() {

        if(stack1.empty()){

            while(!stack2.empty()){
                 stack1.push(stack2.pop());
           	}
        }
        return stack1.pop();
    }
    
    public int peek() {
          if(stack1.empty()){

            while(!stack2.empty()){
                 stack1.push(stack2.pop());
            }
        }
        return stack1.peek();
    }
    
    public boolean empty() {
        //  if(stack1.empty()){

        //     while(!stack2.empty()){
        //          stack1.push(stack2.pop());
        //     }
           
        // }
        return stack1.isEmpty() & stack2.isEmpty();
    }
}

/**
 * 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();
 * boolean param_4 = obj.empty();
 */

[时空分析]

时间复杂度:push 和 empty 为 O(1),pop 和 为均摊 O(1)。对于每个元素,至多入栈和出栈各两次,故均摊复杂度为 O(1)。

空间复杂度:O(n)。其中 n 是操作总数。对于有 n 次 push 操作的情况,队列中会有 n 个元素,故空间复杂度为 O(n)。

lt.225-队列模拟栈

[案例需求]
在这里插入图片描述

[思路分析]

  • 用两个队列模拟实现栈
    • 主队列q1, 辅助队列q2
    • 当主队列q1模拟入栈时, 要把q1的元素全部出队到q2中, 然后入队, 再把q2的元素全部出队q1中

[代码实现]

class MyStack {

    /**
        用两个队列模拟实现栈
        主队列q1, 辅助队列q2
        当主队列q1模拟入栈时, 要把q1的元素全部出队到q2中, 然后入队, 再把q2的元素全部出队q1中

     */
    Queue<Integer> q1;
    Queue<Integer> q2;

    public MyStack() {

       
        //初始化两个队列
        //使用LinkedList, 
        q1 = new LinkedList<Integer>();
        q2 = new LinkedList<Integer>();

    }
    
    ///
    // q1和q2不是固定的主和辅的关系
    public void push(int x) {
        
        q2.offer(x);

        while(!q1.isEmpty()){
            q2.offer(q1.poll());
        }

        //把q2变为q1, 给q1穿上q2的衣服
        Queue<Integer> temp = q1;
        q1 = q2;
        q2 = temp;
    }
    
    public int pop() {
        return q1.poll();
    }
    
    public int top() {
        return q1.peek();
    }
    
    public boolean empty() {
        if(q1.isEmpty())return true;
        return false;
    }
}

/**
 * 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();
 * boolean param_4 = obj.empty();
 */

[时空分析]

posted @   青松城  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示