返回
技术实践:打造完美的双端队列——LeetCode 641 深度解析
前端
2023-11-14 22:49:52
在计算机科学领域,队列是一种常见的数据结构,它遵循先进先出(FIFO)的原则。与普通的队列不同,循环双端队列允许我们在队列的两端进行插入和删除操作,这使其更加灵活和高效。
要设计一个循环双端队列,我们需要使用两个指针来分别指向队头和队尾。当我们在队头插入一个元素时,我们将队头指针后移一位;当我们在队尾插入一个元素时,我们将队尾指针前移一位。当我们在队头删除一个元素时,我们将队头指针前移一位;当我们在队尾删除一个元素时,我们将队尾指针后移一位。
为了避免指针越界,我们可以使用一个数组来存储队列中的元素,并使用两个变量来记录队头和队尾的位置。当队头指针到达数组的末尾时,我们将它重置为数组的开头;当队尾指针到达数组的开头时,我们将它重置为数组的末尾。
class CircularDeque {
private int[] elements;
private int head;
private int tail;
private int size;
public CircularDeque(int k) {
elements = new int[k];
head = 0;
tail = 0;
size = 0;
}
public boolean insertFront(int value) {
if (isFull()) {
return false;
}
head = (head - 1 + elements.length) % elements.length;
elements[head] = value;
size++;
return true;
}
public boolean insertLast(int value) {
if (isFull()) {
return false;
}
elements[tail] = value;
tail = (tail + 1) % elements.length;
size++;
return true;
}
public boolean deleteFront() {
if (isEmpty()) {
return false;
}
head = (head + 1) % elements.length;
size--;
return true;
}
public boolean deleteLast() {
if (isEmpty()) {
return false;
}
tail = (tail - 1 + elements.length) % elements.length;
size--;
return true;
}
public int getFront() {
if (isEmpty()) {
return -1;
}
return elements[head];
}
public int getRear() {
if (isEmpty()) {
return -1;
}
return elements[(tail - 1 + elements.length) % elements.length];
}
public boolean isEmpty() {
return size == 0;
}
public boolean isFull() {
return size == elements.length;
}
}
通过 LeetCode 641 题的练习,我们可以巩固我们对循环双端队列的理解。在这道题中,我们需要设计一个循环双端队列,并实现以下操作:
pushFront(value)
:将一个元素插入到队列的前面。pushBack(value)
:将一个元素插入到队列的后面。popFront()
:从队列的前面删除一个元素。popBack()
:从队列的后面删除一个元素。front()
:返回队列前面的元素。back()
:返回队列后面的元素。empty()
:判断队列是否为空。
为了解决这道题,我们可以使用上面介绍的循环双端队列的实现。我们可以使用一个数组来存储队列中的元素,并使用两个变量来记录队头和队尾的位置。当我们在队头插入一个元素时,我们将队头指针后移一位;当我们在队尾插入一个元素时,我们将队尾指针前移一位。当我们在队头删除一个元素时,我们将队头指针前移一位;当我们在队尾删除一个元素时,我们将队尾指针后移一位。
class Solution {
/**
* Initialize your data structure here. Set the size of the deque to be k.
*/
public MyCircularDeque(int k) {
elements = new int[k];
head = 0;
tail = 0;
size = 0;
}
/**
* Adds an item at the front of Deque. Return true if the operation is successful.
*/
public boolean insertFront(int value) {
if (isFull()) {
return false;
}
head = (head - 1 + elements.length) % elements.length;
elements[head] = value;
size++;
return true;
}
/**
* Adds an item at the rear of Deque. Return true if the operation is successful.
*/
public boolean insertLast(int value) {
if (isFull()) {
return false;
}
elements[tail] = value;
tail = (tail + 1) % elements.length;
size++;
return true;
}
/**
* Deletes an item from the front of Deque. Return true if the operation is successful.
*/
public boolean deleteFront() {
if (isEmpty()) {
return false;
}
head = (head + 1) % elements.length;
size--;
return true;
}
/**
* Deletes an item from the rear of Deque. Return true if the operation is successful.
*/
public boolean deleteLast() {
if (isEmpty()) {
return false;
}
tail = (tail - 1 + elements.length) % elements.length;
size--;
return true;
}
/**
* Get the front item from the deque.
*/
public int getFront() {
if (isEmpty()) {
return -1;
}
return elements[head];
}
/**
* Get the last item from the deque.
*/
public int getRear() {
if (isEmpty()) {
return -1;
}
return elements[(tail - 1 + elements.length) % elements.length];
}
/**
* Checks whether the circular deque is empty or not.
*/
public boolean isEmpty() {
return size == 0;
}
/**
* Checks whether the circular deque is full or not.
*/
public boolean isFull() {
return size == elements.length;
}
private int[] elements;
private int head;
private int tail;
private int size;
}
通过对循环双端队列的学习和 LeetCode 641 题的练习,我们加深了对数据结构和算法的理解。希望这篇文章能够帮助您在计算机科学的道路上更进一步。