LeetCode[641]设计循环双端队列

难度:中等

题目:

设计实现双端队列。

要求:

实现 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
  • insertFrontinsertLastdeleteFrontdeleteLastgetFrontgetRearisEmptyisFull 调用次数不大于 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;
        }
    }

运行结果:

如果您还有什么疑问或解答有问题,可在下方评论,我会及时回复。 

系列持续更新中,点个订阅吧

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月亮被咬碎成星星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值