难度:中等
题目:
设计实现双端队列。
要求:
实现
MyCircularDeque
类:
MyCircularDeque(int k)
:构造函数,双端队列最大为k
。boolean insertFront()
:将一个元素添加到双端队列头部。 如果操作成功返回true
,否则返回false
。boolean insertLast()
:将一个元素添加到双端队列尾部。如果操作成功返回true
,否则返回false
。boolean deleteFront()
:从双端队列头部删除一个元素。 如果操作成功返回true
,否则返回false
。boolean deleteLast()
:从双端队列尾部删除一个元素。如果操作成功返回true
,否则返回false
。int getFront()
):从双端队列头部获得一个元素。如果双端队列为空,返回-1
。int getRear()
:获得双端队列的最后一个元素。 如果双端队列为空,返回-1
。boolean isEmpty()
:若双端队列为空,则返回true
,否则返回false
。boolean isFull()
:若双端队列满了,则返回true
,否则返回false
。
示例一:
输入 ["MyCircularDeque", "insertLast", "insertLast", "insertFront", "insertFront", "getRear", "isFull", "deleteLast", "insertFront", "getFront"]
[ [3], [1], [2], [3], [4], [], [], [], [4], [] ]
输出 [null, true, true, true, false, 2, true, true, true, 4]
解释 MyCircularDeque circularDeque = new MycircularDeque(3); // 设置容量大小为3 circularDeque.insertLast(1); // 返回 true
circularDeque.insertLast(2); // 返回 true
circularDeque.insertFront(3); // 返回 true
circularDeque.insertFront(4); // 已经满了,返回 false
circularDeque.getRear(); // 返回 2
circularDeque.isFull(); // 返回 true
circularDeque.deleteLast(); // 返回 true
circularDeque.insertFront(4); // 返回 true
circularDeque.getFront(); // 返回 4
提示:
1 <= k <= 1000
0 <= value <= 1000
insertFront
,insertLast
,deleteFront
,deleteLast
,getFront
,getRear
,isEmpty
,isFull
调用次数不大于2000
次
Related Topics
- 设计
- 队列
- 数组
- 链表
重点!!!解题思路———数组解法 and 链表解法
一:链表解法
第一步:
创建一个内部类class Node,让其节点既能往前走,又能往后走,做到双端队列
第二步:
当我们向队首添加时,我们先要判断此时队列里是否有元素,如果没有元素,我们让头部节点fount和尾部节点rear都等于新添加的节点node
如果有元素,那么我们让node的下一个节点为头节点fount,
fount的前一个节点为node,
然后让fount节点向前走一步。(fount永远在队列头部)
第三步:
当我们向队尾添加时,我们还是先要此时队列里是否有元素,如果没有元素,我们让头部节点fount和尾部节点rear都等于新添加的节点node
如果有元素,那么我们让rear的下一个节点为node
node的前一个节点为rear,
然后我们让rear节点向后走一步。(rear永远在队列尾部)
源码:
class MyCircularDeque {
class Node{
int val;
Node pre; //节点的前一个值
Node next; //节点的下一个值
public Node(int val) { //节点初始化
this.val = val;
this.pre= null;
this.next= null;
}
}
Node fount,rear; //定义头部节点 尾部节点
int cnt,max; //cnt为当前队列长度,max为队列默认长度
public MyCircularDeque(int k) { //队列初始化
cnt=0;
max=k;
}
public boolean insertFront(int value) {
if (isFull()) return false;
Node node = new Node(value); //新建立一个节点node,并让其值等于value
if(cnt==0){
fount=rear=node;
}else {
node.next=fount;
fount.pre=node;
fount=fount.pre;
}
cnt++;
return true;
}
public boolean insertLast(int value) {
if (isFull()) return false;
Node node = new Node(value); //新建立一个节点node,并让其值等于value
if(cnt==0){
fount=rear=node;
}else {
rear.next=node;
node.pre=rear;
rear=rear.next;
}
cnt++;
return true;
}
public boolean deleteFront() { //删除第一个节点,我们让头部节点向后走一步
if (isEmpty()) return false;
fount=fount.next;
cnt--;
return true;
}
public boolean deleteLast() { //删除尾部节点,我们让尾部节点向前走一步
if (isEmpty()) return false;
rear=rear.pre;
cnt--;
return true;
}
public int getFront() {
if (isEmpty()) return -1;
return fount.val;
}
public int getRear() {
if (isEmpty()) return -1;
return rear.val;
}
public boolean isEmpty() {
return cnt==0;
}
public boolean isFull() {
return cnt==max;
}
}
运行结果:
二:数组解法
第一步:
定义两个用来标记循环队列头尾指针的,一个为head,一个为tail
我们让tail始终处于尾部的下一个位置
第二步:
定义一个计数器cnt用来记录目前队列的大小
第三步:
向队首添加时,我们肯定是让head-1,当head为数组头部时,head-1<0
我们不能让这种情况出现
所以head=(head-1+数组长度)%数组长度 让队列不假溢出
第四步:
向队尾添加时,我们让tail+1,当tail为数组尾部时,tail+1会大于数组长度
我们也不能让这种情况出现
所以tail=(tail+1)%数组长度 当队列不假溢出
第五步:
队首出队时,队尾出队时与前面无异
源码:
class MyCircularDeque {
int[] arr;
int head,tail,cnt,max;
public MyCircularDeque(int k) { //进行队列的初始化 max为队列长度 cnt为计数器
arr=new int[k];
head=0;
tail=0;
cnt=0;
max=k;
}
public boolean insertFront(int value) {
if (isFull()) return false;
head=(head-1+max)%max;
arr[head]=value;
cnt++;
return true;
}
public boolean insertLast(int value) {
if (isFull()) return false;
arr[tail]=value;
tail=(tail+1)%max;
cnt++;
return true;
}
public boolean deleteFront() { //队首出队时,让head+1,并且不能让队列假溢出
if(isEmpty()) return false;
head=(head+1)%max;
cnt--;
return true;
}
public boolean deleteLast() { //队尾出队时,让tail-1,并且不能让队列假溢出
if(isEmpty()) return false;
tail=(tail-1+max)%max;
cnt--;
return true;
}
public int getFront() {
if(isEmpty()) return -1;
return arr[head];
}
public int getRear() {
if (isEmpty()) return -1;
return arr[(tail-1+max)%max]; //因为tail永远在最后一个元素的下一个节点,所以tail-1才是队尾元素
}
public boolean isEmpty() {
return cnt==0;
}
public boolean isFull() {
return cnt==max;
}
}
运行结果:
如果您还有什么疑问或解答有问题,可在下方评论,我会及时回复。
系列持续更新中,点个订阅吧