【LeetCode每日一题】——641.设计循环双端队列

文章目录

  • 一【题目类别】
  • 二【题目难度】
  • 三【题目编号】
  • 四【题目描述】
  • 五【题目示例】
  • 六【题目提示】
  • 七【解题思路】
  • 八【时间频度】
  • 九【代码实现】
  • 十【提交结果】

一【题目类别】

  • 队列

二【题目难度】

  • 中等

三【题目编号】

  • 641.设计循环双端队列

四【题目描述】

  • 设计实现双端队列。
  • 你的实现需要支持以下操作:
  • MyCircularDeque(k):构造函数,双端队列的大小为k。
  • insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true。
  • insertLast():将一个元素添加到双端队列尾部。如果操作成功返回 true。
  • deleteFront():从双端队列头部删除一个元素。 如果操作成功返回 true。
  • deleteLast():从双端队列尾部删除一个元素。如果操作成功返回 true。
  • getFront():从双端队列头部获得一个元素。如果双端队列为空,返回 -1。
  • getRear():获得双端队列的最后一个元素。 如果双端队列为空,返回 -1。
  • isEmpty():检查双端队列是否为空。
  • isFull():检查双端队列是否满了。

五【题目示例】

  • 示例:
    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, 1000]
  • 操作次数的范围为 [1, 1000]
  • 请不要使用内置的双端队列库。

七【解题思路】

  • 唯一需要注意一点就是头尾指针的位置问题,做减法时要注意不要越界,如果做减法为-1,取模还是-1,就越界了,解决办法就是加上队列的长度再取模,加法没有这个问题,其余和622.设计循环队列一样

八【时间频度】

  • 时间复杂度: O ( 1 ) O(1) O(1)

九【代码实现】

  1. Java语言版
package Queue;

public class p641_DesignCircularDeque {

    private static int[] queue; // 数组模拟队列
    private static int front; // 队列头指针
    private static int rear; // 队列尾指针
    private static int len; // 需要生成的长度

    public static void main(String[] args) {
        p641_DesignCircularDeque res1 = new p641_DesignCircularDeque(4);
        boolean res2 = insertFront(9);
        boolean res3 = deleteFront();
        int res4 = getRear();
        int res5 = getFront();
        int res6 = getFront();
        boolean res7 = deleteFront();
        boolean res8 = insertFront(6);
        boolean res9 = insertLast(5);
        boolean res10 = insertFront(9);
        int res11 = getFront();
        boolean res12 = insertFront(6);
        System.out.println(res1 + " " + res2 + " " + res3 + " " + res4 + " " + res5 + " " + res6 + " " + res7 + " " + res8 + " " + res9 + " " + res10 + " " + res11 + " " + res12);
    }

    // 初始化双端队列
    public p641_DesignCircularDeque(int k) {
        len = k + 1; // 这里+1是因为要预留一个元素位置
        queue = new int[len];
        front = 0;
        rear = 0;
    }

    // 在双端队列头插入元素
    public static boolean insertFront(int value) {
        if (isFull()) {
            return false;
        }
        front = (front - 1 + len) % len; // 这里是和622不同的地方,因为有可能是-1,所有要+len之后再取模,这样就能形成“环”
        queue[front] = value;
        return true;
    }

    // 在双端队列尾插入元素
    public static boolean insertLast(int value) {
        if (isFull()) {
            return false;
        }
        queue[rear] = value;
        rear = (rear + 1) % len; // 取模就是转了一圈,如果到了队列最后一个,那么下一个就到了队列头
        return true;
    }

    // 删除双端队列头元素
    public static boolean deleteFront() {
        if (isEmpty()) {
            return false;
        }
        front = (front + 1) % len; // 这里也是和622不同的地方,因为front就指向当前元素,所以只需让他转圈即可
        return true;
    }

    // 删除双端队列尾元素
    public static boolean deleteLast() {
        if (isEmpty()) {
            return false;
        }
        rear = (rear - 1 + len) % len; // 因为尾指针最后一次+1了,所以队尾元素要-1,但是涉及到转圈的问题
        return true;
    }

    // 得到双端队列头元素
    public static int getFront() {
        if (isEmpty()) {
            return -1;
        }
        return queue[(front + len) % len]; // 因为头指针指哪就是哪,所以直接返回,但是涉及到转圈的问题
    }

    // 得到双端队列尾元素
    public static int getRear() {
        if (isEmpty()) {
            return -1;
        }
        return queue[(rear - 1 + len) % len]; // 因为尾指针最后一次+1了,所以队尾元素要-1,但是涉及到转圈的问题
    }

    // 判断双端队列是否为空
    public static boolean isEmpty() {
        return rear == front;
    }

    // 判断双端队列是否满
    public static boolean isFull() {
        return (rear + 1) % len == front;
    }

}
  1. C语言版
#include
#include
#include
#include

/*循环队列结构体*/
typedef struct
{
	int *data; /*数组模拟队列*/
	int front; /*头指针*/
	int rear; /*尾指针*/
	int len; /*数组长度*/
}MyCircularDeque;

/*初始化队列*/
MyCircularDeque* myCircularDequeCreate(int k)
{
	MyCircularDeque* queue = (MyCircularDeque *)malloc(sizeof(MyCircularDeque));
	queue->len = k + 1; /*这里+1是因为要预留一个元素位置*/
	queue->data = (int *)malloc(queue->len * sizeof(int));
	queue->front = 0;
	queue->rear = 0;
	return queue;
}

/*判断双端队列是否为空*/
bool myCircularDequeIsEmpty(MyCircularDeque* obj)
{
	return obj->rear == obj->front;
}

/*判断双端队列是否满*/
bool myCircularDequeIsFull(MyCircularDeque* obj)
{
	return (obj->rear + 1) % obj->len == obj->front;
}

/*向队列头插入元素*/
bool myCircularDequeInsertFront(MyCircularDeque* obj, int value)
{
	if (myCircularDequeIsFull(obj))
	{
		return false;
	}
	obj->front = (obj->front - 1 + obj->len) % obj->len;
	obj->data[obj->front] = value;
	return true;
}

/*向队列尾插入元素*/
bool myCircularDequeInsertLast(MyCircularDeque* obj, int value)
{
	if (myCircularDequeIsFull(obj))
	{
		return false;
	}
	obj->data[obj->rear] = value;
	obj->rear = (obj->rear + 1) % obj->len;
	return true;
}

/*删除队列头元素*/
bool myCircularDequeDeleteFront(MyCircularDeque* obj)
{
	if (myCircularDequeIsEmpty(obj))
	{
		return false;
	}
	obj->front = (obj->front + 1) % obj->len;
	return true;
}

/*删除队列尾元素*/
bool myCircularDequeDeleteLast(MyCircularDeque* obj)
{
	if (myCircularDequeIsEmpty(obj))
	{
		return false;
	}
	obj->rear = (obj->rear - 1 + obj->len) % obj->len;
	return true;
}

/*返回队列头元素*/
int myCircularDequeGetFront(MyCircularDeque* obj)
{
	if (myCircularDequeIsEmpty(obj))
	{
		return -1;
	}
	return obj->data[(obj->front + obj->len) % obj->len];
}

/*返回队列尾元素*/
int myCircularDequeGetRear(MyCircularDeque* obj)
{
	if (myCircularDequeIsEmpty(obj))
	{
		return -1;
	}
	return obj->data[(obj->rear - 1 + obj->len) % obj->len];
}

/*释放元素*/
void myCircularDequeFree(MyCircularDeque* obj)
{
	free(obj->data);
	free(obj);
}

/*主函数省略*/

十【提交结果】

  1. Java语言版
    【LeetCode每日一题】——641.设计循环双端队列_第1张图片
  2. C语言版
    【LeetCode每日一题】——641.设计循环双端队列_第2张图片

你可能感兴趣的:(LeetCode,leetcode,数据结构,算法,循环双端队列,设计)