leetcode brush questions (6)

Hello friends, today is the sixth chapter of my leetcode brushing series. This article will be related to the knowledge of queues, because it is more complicated to implement these knowledge in C language, so we will only use Java to implement.

design circular queue

Leetcode Design Circular Queue (Difficulty: Simple)

Topic requirements

Design your circular queue implementation. A circular queue is a linear data structure whose operation is based on the FIFO (first in first out) principle and the tail of the queue is connected after the head of the queue to form a loop. It is also known as a "ring buffer".

One benefit of circular queues is that we can utilize previously used space on this queue. In a normal queue, once a queue is full, we cannot insert the next element, even if there is still room at the front of the queue. But with a circular queue, we can use this space to store new values.

Your implementation should support the following operations:

MyCircularQueue(k): Constructor, set the queue length to k.
Front: Get elements from the front of the queue. Returns -1 if the queue is empty.
Rear: Get the element at the end of the queue. Returns -1 if the queue is empty.
enQueue(value): Insert an element into the circular queue. Returns true if the insertion was successful.
deQueue(): Remove an element from the circular queue. Returns true if the deletion was successful.
isEmpty(): Checks if the circular queue is empty.
isFull(): Checks if the circular queue is full.

This is the interface provided by the topic

class MyCircularQueue {
    
    

    public MyCircularQueue(int k) {
    
    

    }
    
    public boolean enQueue(int value) {
    
    

    }
    
    public boolean deQueue() {
    
    

    }
    
    public int Front() {
    
    

    }
    
    public int Rear() {
    
    

    }
    
    public boolean isEmpty() {
    
    

    }
    
    public boolean isFull() {
    
    

    }
}

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

use case input

Example:

MyCircularQueue circularQueue = new MyCircularQueue(3); // Set the length to 3
circularQueue.enQueue(1); // Return true
circularQueue.enQueue(2); // Return true
circularQueue.enQueue(3); // Return true
circularQueue. enQueue(4); // returns false, the queue is full
circularQueue.Rear(); // returns 3
circularQueue.isFull(); // returns true
circularQueue.deQueue(); // returns true
circularQueue.enQueue(4); // returns true
circularQueue.Rear(); // returns 4

hint

All values ​​are in the range 0 to 1000;
operands will be in the range 1 to 1000;
please do not use the built-in queue library.

Question ideas

Before doing this question, we need to know what a circular queue is. Ordinary queues, we should know that queues are a kind of data structure, which is characterized by one end in, one end out, first in first out (FIFO). But when it is out of the queue, the space at the head of the queue is vacated, and when we insert data, we can only insert from the end of the queue, so the space at the head of our queue cannot be used, which causes space shortage. waste. And the principle of our circular linked list is that when the end of our team reaches the end of the array, we come back to use the space that the head of the team has gone out.

insert image description here
When the queue is empty, both front and rear point to the position of 0 in the table below the array. When inserting data into the queue, our rear moves backward, rear = (rear+1)%length, when (rear+ 1) When %length == front, the queue is full.
insert image description here

insert image description here

insert image description here

Code

class MyCircularQueue {
    
    

//用数组实现队列
    private int[] elem;
    //队列的头
    private int front;
    //队列的尾
    private int rear;

    public MyCircularQueue(int k) {
    
    
    //这里我们浪费一个空间来判断队列是否满了
        this.elem = new int[k+1];
    }

    public boolean enQueue(int value) {
    
    
        if(isFull()) {
    
    
            return false;
        }
        this.elem[rear] = value;
        rear = (rear+1)%elem.length;
        return true;
    }

    public boolean deQueue() {
    
    
        if(isEmpty()) {
    
    
            return false;
        }
        front = (front+1)%elem.length;
        return true;
    }

    public int Front() {
    
    
        if(isEmpty()) {
    
    
            return -1;
        }
        return elem[front];
    }

    public int Rear() {
    
    
        if(isEmpty()) {
    
    
            return -1;
        }
        //因为rear总是指向队列尾的下一个位置,
        //所以我们返回队尾的值的时候就返回rear的前一个位置的值,
        //但是当rear为0时,我们不能返回-1,我们返回数组下标最大的值
        int index = (rear == 0) ? elem.length-1:rear-1;
        return elem[index];
    }

    public boolean isEmpty() {
    
    
        if(front == rear) {
    
    
            return true;
        }
        return false;
    }

    public boolean isFull() {
    
    
        return (rear+1)%elem.length == front;
    }
}

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

insert image description here

Implementing a queue with a stack

Leetcode uses a stack to implement a queue (difficulty: simple)

Topic requirements

Please use only two stacks to implement a first-in-first-out queue. The queue should support all operations supported by general queues (push, pop, peek, empty):

Implement the MyQueue class:

void push(int x) pushes element x to the end of the queue
int pop() removes from the beginning of the queue and returns the element
int peek() returns the element at the beginning of the queue
boolean empty() returns true if the queue is empty; otherwise, Return false
Description:

You can only use standard stack operations -- that is, only push to top, peek/pop from top, size, and is empty operations are legal.
Your language may not support stacks. You can use list or deque (double-ended queue) to simulate a stack, as long as it is a standard stack operation.

This is the interface provided by the topic

class MyQueue {
    
    

    public MyQueue() {
    
    

    }
    
    public void push(int x) {
    
    

    }
    
    public int pop() {
    
    

    }
    
    public int peek() {
    
    

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

use case input

Example 1:

Input:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
Output:
[null, null, null, 1, 1, false]

解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false

hint

1 <= x <= 9
up to 100 calls to push, pop, peek and empty
assuming all operations are valid (e.g. an empty queue will not call pop or peek)

Question ideas

We all know that the characteristics of stacks and queues are different. The stack is one end in and out, first in last out (FILO), which is different from the queue's one end in and one end out, first in first out (FIFO). That is, it is difficult for us to implement a queue with a stack, so we need to implement a queue with two stacks stack1 and stack2. When we insert data, if satck2 is not empty, we need to pop out the data in stack2 and insert it into satck1, and then insert the data to be inserted into stack1. When we take out the data, we will put it in satack1 The data of is popped and inserted into satck2, and then we pop stack2.
Let's look at an example first: first push1, 2, 3, 4, then pop, then push5
insert image description here
inserts 1, 2, 3, 4
insert image description here
to take out data
insert image description here
, inserts 5
insert image description here
to take out data
insert image description here

Code

class MyQueue {
    
    
    private Stack<Integer> stack1;
    private Stack<Integer> stack2;

    public MyQueue() {
    
    
        stack1 = new Stack<>();
        stack2 = new Stack<>();
    }

    public void push(int x) {
    
    
        while(!stack2.isEmpty()) {
    
    
            stack1.push(stack2.pop());
        }
        stack1.push(x);
    }

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

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

    public boolean empty() {
    
    
        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();
 */

insert image description here

Implementing a stack with a queue

Leetcode uses queues to implement stacks (difficulty: simple)

Topic requirements

Please use only two queues to implement a last-in-first-out (LIFO) stack, and support all four operations (push, top, pop, and empty) of a normal stack.

Implement the MyStack class:

void push(int x) pushes the element x onto the top of the stack.
int pop() removes and returns the top element of the stack.
int top() Returns the top element of the stack.
boolean empty() Returns true if the stack is empty; otherwise, returns false.

Notice:

You can only use the basic operations of the queue - that is, push to back, peek/pop from front, size and is empty.
Your language may not support queues. You can use list (list) or deque (double-ended queue) to simulate a queue, as long as it is a standard queue operation.

use case input

Example:

Input:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
Output:
[null, null, null, 2, 2, false]

Explanation:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // returns 2
myStack.pop(); // returns 2
myStack.empty(); // return False

This is the interface provided by the topic

class MyStack {
    
    

    public MyStack() {
    
    

    }
    
    public void push(int x) {
    
    

    }
    
    public int pop() {
    
    

    }
    
    public int top() {
    
    

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

Question ideas

For this topic, we also cannot implement a stack using only one queue, so we still need two queues qu1 and qu2. When we insert data, we insert it into a non-empty queue. If both queues are empty, we insert it into qu1; when we need to take out data, we need to pop size-1 data from the non-empty queue and insert it into In that empty queue, and then pop the remaining data in the non-empty queue is the data we need.

For example: we need to insert 1, 2, 3, 4 first, then eject once, then insert 5, and eject again.
insert image description here
Pop 4
insert image description here
Insert 5
insert image description here
Pop 5
insert image description here

Code

class MyStack {
    
    

    private Queue<Integer> qu1;
    private Queue<Integer> qu2;
    public MyStack() {
    
    
        qu1 = new LinkedList<>();
        qu2 = new LinkedList<>();
    }

    public void push(int x) {
    
    
        if(!qu1.isEmpty()) {
    
    
            qu1.offer(x);
        } else if(!qu2.isEmpty()) {
    
    
            qu2.offer(x);
        } else {
    
    
            qu1.offer(x);
        }
    }

    public int pop() {
    
    
        if(empty()) {
    
    
            return -1;
        }
        if(!qu1.isEmpty()) {
    
    
            int size = qu1.size();
            for(int i = 0; i<size-1; i++) {
    
    
                int val = qu1.poll();
                qu2.offer(val);
            }
            return qu1.poll();
        } else {
    
    
            int size = qu2.size();
            for(int i = 0; i<size-1; i++) {
    
    
                int val = qu2.poll();
                qu1.offer(val);
            }
            return qu2.poll();
        }
    }

    public int top() {
    
    
        if(empty()) {
    
    
            return -1;
        }
        int val1 = -1;
        if(!qu1.isEmpty()) {
    
    
            int size = qu1.size();
            for(int i = 0; i<size; i++) {
    
    
                int val = qu1.poll();
                val1 = val;
                qu2.offer(val);
            }
        } else {
    
    
            int size = qu2.size();
            for(int i = 0; i<size; i++) {
    
    
                int val = qu2.poll();
                val1 = val;
                qu1.offer(val);
            }
        }
        return val1;
    }

    public boolean empty() {
    
    
        return qu1.isEmpty() && qu2.isEmpty();
    }
}

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

insert image description here

Guess you like

Origin blog.csdn.net/m0_73888323/article/details/130167165