设计循环双端队列

84 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情

一、题目

LeetCode 设计循环双端队列

设计实现双端队列。

实现 MyCircularDeque 类:

MyCircularDeque(int k) :构造函数,双端队列最大为 k 。
boolean insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true ,否则返回 falseboolean insertLast() :将一个元素添加到双端队列尾部。如果操作成功返回 true ,否则返回 falseboolean deleteFront() :从双端队列头部删除一个元素。 如果操作成功返回 true ,否则返回 falseboolean deleteLast() :从双端队列尾部删除一个元素。如果操作成功返回 true ,否则返回 falseint getFront() ):从双端队列头部获得一个元素。如果双端队列为空,返回 -1 。
int getRear() :获得双端队列的最后一个元素。 如果双端队列为空,返回 -1boolean isEmpty() :若双端队列为空,则返回 true ,否则返回 false  。
boolean isFull() :若双端队列满了,则返回 true ,否则返回 false

提示:

1 <= k <= 1000
0 <= value <= 1000
insertFront, insertLast, deleteFront, deleteLast, getFront, getRear, isEmpty, isFull  调用次数不大于 2000 

二、题解

根据题目要求设计一个循环双端队列,并且完成实现类中相对应的方法。

方法一

可以使用数组来模拟队列实现循环双端队列,具体的需要的类属性:

  • elements整形数组,当成队列使用,存储队列的元素;
  • size队列大小,表示队列的元素最大值;
  • head头部指针,指向队列的头部元素;
  • tail尾部指针,指向队列的尾部元素。

然后对应的实现具体的方法,

  • MyCircularDeque(int k)方法构造函数,构造队列大小,首先初始化elements数组大小为k + 1,然后对应的size也为k + 1,最后初始的两个指针指向0位置;
  • insertFront(int value)方法将元素添加到队列头部,首先判断如果队列已满则返回false,否则获取队列头部位置(head - 1 + size) % size,并且更新elements数组中头部位置head的值为value
  • insertLast(int value)方法将元素添加到队列尾部,首先判断如果队列已满则返回false,否则更新elements数组中尾部位置tail的值为value,并且获取尾部位置(tail + 1) % size
  • deleteFront()方法删除队列头部的一个元素,首先判断如果队列元素为空则返回false,否则直接更新head指针位置(head + 1) % size
  • deleteLast()方法删除队列尾部的一个元素,首先判断如果队列元素为空则返回false,否则直接更新tail指针位置(tail - 1 + size) % size
  • getFront()方法获取一个队列头部元素,首先判断如果队列为空的话则返回-1,否则返回elements数组中对应的头部位置元素;
  • getRear()方法获取一个队列尾部元素,首先判断如果队列为空的话则返回-1,否则返回elements数组中对应尾部位置的元素;
  • isEmpty()方法判断队列是否为空,判断两个指针headtail位置是否相同,相同的则为空;
  • isFull()方法判断队列元素是否已满,判断两个指针(tail + 1) % size == head相等的就是已满。

三、代码

方法一 Java代码

class MyCircularDeque {
    private int[] elements;
    private int head;
    private int tail;
    private int size;

    public MyCircularDeque(int k) {
        size = k + 1;
        tail = head = 0;
        elements = new int[k + 1];
    }

    public boolean insertFront(int value) {
        if (isFull()) {
            return false;
        }
        head = (head - 1 + size) % size;
        elements[head] = value;
        return true;
    }

    public boolean insertLast(int value) {
        if (isFull()) {
            return false;
        }
        elements[tail] = value;
        tail = (tail + 1) % size;
        return true;
    }

    public boolean deleteFront() {
        if (isEmpty()) {
            return false;
        }
        head = (head + 1) % size;
        return true;
    }

    public boolean deleteLast() {
        if (isEmpty()) {
            return false;
        }
        tail = (tail - 1 + size) % size;
        return true;
    }

    public int getFront() {
        if (isEmpty()) {
            return -1;
        }
        return elements[head];
    }

    public int getRear() {
        if (isEmpty()) {
            return -1;
        }
        return elements[(tail - 1 + size) % size];
    }

    public boolean isEmpty() {
        return head == tail;
    }

    public boolean isFull() {
        return head == (tail + 1) % size;
    }
}

时间复杂度: O(1),只需常数的操作时间。

空间复杂度: O(n),需要使用的数组当成队列模拟。