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出元素, 能够动态的返回某一时间点下的主栈中的最小值;
- 稍加思考, 我们需要一个辅助栈, 记录主栈某次操作后主栈中的最小值;
- 如何记录? 当然是在主栈入栈和出栈时, 把这个出栈或入栈的元素和辅助栈的栈顶元素进行比较- 辅助栈, 我们也可称之为最小栈(存储每次主栈操作后, 栈中的最小值)
-  
    - 主栈入栈一个元素时, 辅助栈为空, 无条件入栈这个元素
 
- 主栈入栈一个元素时, 
-  
    - 主栈入栈一个元素时, 入栈元素<=辅助栈栈顶元素, 主栈入栈, 辅助栈也入栈;
 
- 主栈入栈一个元素时, 
-  
    - 主栈出栈一个元素时, 出栈元素==辅助站栈顶元素, 主栈出栈, 辅助栈也出栈;
 [代码实现]
 
- 主栈出栈一个元素时, 
 
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();
 */
[时空分析]
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号