【发布时间】:2019-04-13 11:03:11
【问题描述】:
我正在从问题Design Circular Queue - LeetCode中学习队列
设计循环队列的实现。循环队列是一种线性数据结构,其操作基于FIFO(先进先出)原则,最后一个位置与第一个位置连接形成一个圆圈。也称为“环形缓冲区”。
循环队列的一个好处是我们可以利用队列前面的空间。在普通队列中,一旦队列满了,即使队列前面有空间,我们也无法插入下一个元素。但是使用循环队列,我们可以利用空间来存储新值。
您的实现应支持以下操作:
MyCircularQueue(k):构造函数,设置队列大小为k。Front:从队列中获取最前面的项目。如果队列为空,则返回 -1。Rear:从队列中获取最后一项。如果队列为空,则返回 -1。enQueue(value):向循环队列中插入一个元素。如果操作成功,则返回 true。deQueue():从循环队列中删除一个元素。如果操作成功,则返回 true。isEmpty():检查循环队列是否为空。isFull():检查循环队列是否已满。示例:
MyCircularQueue circularQueue = new MyCircularQueue(3); // set the size to be 3 circularQueue.enQueue(1); // return true circularQueue.enQueue(2); // return true circularQueue.enQueue(3); // return true circularQueue.enQueue(4); // return false, the queue is full circularQueue.Rear(); // return 3 circularQueue.isFull(); // return true circularQueue.deQueue(); // return true circularQueue.enQueue(4); // return true circularQueue.Rear(); // return 4注意:
- 所有值都将在 [0, 1000] 范围内。
- 操作数将在 [1, 1000] 范围内。
- 请不要使用内置队列库。
我模仿古德里奇的教科书Data Structures and Algorithms in Python并写了一个友好可读的解决方案
1、只有三个数据(_queue、_len、_front)
2、将self._front初始化为0
class MyCircularQueue:
#Runtime: 76 ms, faster than 53.17%
#Memory Usage: 13.6 MB, less than 7.24%
def __init__(self, k: int):
"""
Initialize your data structure here. Set the size of the queue to be k.
"""
self._queue = [None] * k #the basic
self._capacity = k
self._len = 0
#The first three categorize as a group, the 4th as the second group
self._front = 0
#self._rear is not necessary, because rear = front + length -1
def enQueue(self, value: int) -> bool:
"""
Insert an element into the circular queue. Return true if the operation is successful.
"""
if self.isFull(): return False
avail = (self._front + self._len) % (self._capacity)
self._queue[avail] = value
self._len += 1
return True
def deQueue(self) -> bool:
"""
Delete an element from the circular queue. Return true if the operation is successful.
"""
if self.isEmpty():
return False
self._queue[self._front] = None #overrode the current node
self._front = (self._front+1) % self._capacity
self._len -= 1
return True
def Front(self) -> int:
"""
Get the front item from the queue.
"""
if not self.isEmpty():
return self._queue[self._front]
else:
return -1
def Rear(self) -> int:
"""
Get the last item from the queue.
"""
if not self.isEmpty():
_rear = (self._front + self._len - 1) % self._capacity
return self._queue[_rear]
else:
return -1
def isEmpty(self) -> bool:
"""
Checks whether the circular queue is empty or not.
"""
return self._len == 0
def isFull(self) -> bool:
"""
Checks whether the circular queue is full or not.
"""
return self._len == self._capacity
Goodrich 的设计非常好用,读起来也省力。
但是,在阅读其他提交时,通常的做法是将self._fornt 和self._rear 初始化为-1,认为读取或写入都很费力。
摘录一个性能优于 98% 的案例
def deQueue(self):
"""
Delete an element from the circular queue. Return true if the operation is successful.
:rtype: bool
"""
if self.isEmpty():
return False
self.head = (self.head+1) % self.maxlen
self.currlen -= 1
if self.isEmpty(): #have to take care of self.head and self.tail
self.head = -1
self.tail = -1
#another submission which initialize front and rear =-1
def enQueue(self, value: 'int') -> 'bool':
"""
Insert an element into the circular queue. Return true if the operation is successful.
"""
if (self.len == self.capacity): return False
# To check if full
#if (self.rear == self.front - 1 or (self.rear == self.capacity - 1 and self.front == 0) )
if (self.front == -1):
self.front, self.rear = 0, 0
elif (self.rear == self.capacity - 1 and self.front != 0):
# make rear start (case when element was removed from start)
self.rear = 0
else:
self.rear = (self.rear + 1) % self.capacity
self.data[self.rear] = value
self.len += 1
return True
由于python隐藏了大多数实现细节,
将front 或rear 用作-1 有什么好处?
【问题讨论】: