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

lt.622-循环队列

[案例需求]
1. <tag-队列和栈(典型题)>-lt.622-循环队列 + lt.155-最小栈 + lt.232/剑指.09-栈模拟队列 + lt.225-队列模拟栈_第1张图片
[思路分析]

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

[代码实现]

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();
 */

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

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

[案例需求]
1. <tag-队列和栈(典型题)>-lt.622-循环队列 + lt.155-最小栈 + lt.232/剑指.09-栈模拟队列 + lt.225-队列模拟栈_第3张图片

[思路分析]

  • 最小栈, 根据题意, 往主栈中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();
 */

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

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

[案例需求]
1. <tag-队列和栈(典型题)>-lt.622-循环队列 + lt.155-最小栈 + lt.232/剑指.09-栈模拟队列 + lt.225-队列模拟栈_第5张图片1. <tag-队列和栈(典型题)>-lt.622-循环队列 + lt.155-最小栈 + lt.232/剑指.09-栈模拟队列 + lt.225-队列模拟栈_第6张图片

[思路分析]
- 一个栈模拟队列,一个栈辅助
- 将一个栈当作输入栈,用于压入 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-队列模拟栈

[案例需求]
1. <tag-队列和栈(典型题)>-lt.622-循环队列 + lt.155-最小栈 + lt.232/剑指.09-栈模拟队列 + lt.225-队列模拟栈_第7张图片

[思路分析]

[代码实现]

class CQueue {

    Stack<Integer> primaryStack;
    Stack<Integer> resStack;


    public CQueue() {
        primaryStack = new Stack<>();
        resStack = new Stack<>();
    }
    /**
        用栈做队列的方法:
        1. 双栈, 一 个栈用来做输入栈, 另一个栈作为输出栈
        2. 入对列就是往输入栈中输出数据;
        3. 出队就是从输出栈中取出数据;
        4. 最终的一点: 只有在输出栈为空的时候, 输入栈才能往输出栈中存入数据;
     */
    public void appendTail(int value) {
        //入队列: 向输入栈中存入数据
        primaryStack.push(value);
    }
    
    public int deleteHead() {
        
        if(resStack.isEmpty()){
            while(!primaryStack.isEmpty()){
                resStack.push(primaryStack.pop());
            }
        }

        return resStack.isEmpty() ? -1 : resStack.pop();
    }
}

/**
 * Your CQueue object will be instantiated and called as such:
 * CQueue obj = new CQueue();
 * obj.appendTail(value);
 * int param_2 = obj.deleteHead();
 */

[时空分析]

你可能感兴趣的:(#,tag_队列和栈,spark,hadoop,大数据)