Formatted question description: https://leetcode.ca/all/641.html

# 641. Design Circular Deque

Medium

## Description

Design your implementation of the circular double-ended queue (deque).

Your implementation should support following operations:

• MyCircularDeque(k): Constructor, set the size of the deque to be k.
• insertFront(): Adds an item at the front of Deque. Return true if the operation is successful.
• insertLast(): Adds an item at the rear of Deque. Return true if the operation is successful.
• deleteFront(): Deletes an item from the front of Deque. Return true if the operation is successful.
• deleteLast(): Deletes an item from the rear of Deque. Return true if the operation is successful.
• getFront(): Gets the front item from the Deque. If the deque is empty, return -1.
• getRear(): Gets the last item from Deque. If the deque is empty, return -1.
• isEmpty(): Checks whether Deque is empty or not.
• isFull(): Checks whether Deque is full or not.

Example:

MyCircularDeque circularDeque = new MycircularDeque(3); // set the size to be 3
circularDeque.insertLast(1);			// return true
circularDeque.insertLast(2);			// return true
circularDeque.insertFront(3);			// return true
circularDeque.insertFront(4);			// return false, the queue is full
circularDeque.getRear();  			// return 2
circularDeque.isFull();				// return true
circularDeque.deleteLast();			// return true
circularDeque.insertFront(4);			// return true
circularDeque.getFront();			// return 4


Note:

• All values will be in the range of [0, 1000].
• The number of operations will be in the range of [1, 1000].
• Please do not use the built-in Deque library.

## Solution

queue vs deque. Reference: https://www.quora.com/What-is-the-difference-between-queue-and-deque

Queue is who ever gets in first gets out first i.e First In First Out(FIFO). like a line in front of a super market counter. It is used when there is a single resource(cashier) who has to do the tasks(billing) of all the requests(shoppers in line who want to get the items billed)

Deque(pronounced as deck) is double ended queue i.e the elements can be added or removed at either end of the line. It is used in situations when there are multiple requests(customers who want their items to be billed) but the contract is such that as soon as the cashier from other counter completes all the requests he can take over the left over requests(customers) from the opposite end of the line. This helps to use up the resource efficiently and requests are cleared at a faster rate.

Use an array to act as a deque and store the elements. Besides the array that is a data field of the class MyCircularDeque, the other data fields include capacity which is the capacity of the deque, start and end which are the indices of the first element and the last element, and size which is the number of elements in the deque.

For the constructor, given capacity k, initialize the array to be an array of length k and filled with -1, set capacity = k, and set start, end and size to 0.

For method insertFront, return false if the deque is full (checked by calling isFull). If size == 0, then set both start to end to 0. Otherwise, move front one step backward (note that the deque is circular, so if start was previously 0, then end will become capacity - 1 after moving one step backward). Set the element at index start in the array to be the given value, increase size by 1, and return true.

For method insertLast, return false if the deque is full (checked by calling isFull). If size == 0, then set both start to end to 0. Otherwise, move end one step forward (note that the deque is circular, so if end was previously capacity - 1, then end will become 0 after moving one step forward). Set the element at index end in the array to be the given value, increase size by 1, and return true.

For method deleteFront, return false if the deque is empty (checked by calling isEmpty). Set the element at index start to -1, move start one step forward (note that the deque is circular, so if start was previously capacity - 1, then start will become 0 after moving one step forward), decrease size by 1, and return true.

For method deleteLast, return false if the deque is empty (checked by calling isEmpty). Set the element at index end to -1, move end one step backward (note that the deque is circular, so if end was previously 0, then end will become capacity - 1 after moving one step backward), decrease size by 1, and return true.

For method getFront, return the element at index start.

For method getRear, return the element at index end.

For method isEmpty, return true if and only if size == 0.

For method isFull, return true if and only if size == capacity.

• public class Design_Circular_Deque {

// ref: https://www.cnblogs.com/Dylan-Java-NYC/p/12079440.html
class MyCircularDeque {
int [] arr;
int start;
int end;
int len;
int k;

/** Initialize your data structure here. Set the size of the deque to be k. */
public MyCircularDeque(int k) {
arr = new int[k];
start = -1;
end = -1;
len = 0;
this.k = k;
}

/** Adds an item at the front of Deque. Return true if the operation is successful. */
public boolean insertFront(int value) {
if(isFull()){
return false;
}

if(start == -1){
start = 0;
}else{
start = (start - 1 + k) % k;
}

arr[start] = value;
if(end == -1){
end = start;
}

len++;
return true;
}

/** Adds an item at the rear of Deque. Return true if the operation is successful. */
public boolean insertLast(int value) {
if(isFull()){
return false;
}

end = (end + 1) % k;
arr[end] = value;
if(start == -1){
start = end;
}

len++;
return true;
}

/** Deletes an item from the front of Deque. Return true if the operation is successful. */
public boolean deleteFront() {
if(isEmpty()){
return false;
}

start = (start + 1) % k;
len--;
return true;
}

/** Deletes an item from the rear of Deque. Return true if the operation is successful. */
public boolean deleteLast() {
if(isEmpty()){
return false;
}

end = (end - 1 + k) % k;
len--;
return true;
}

/** Get the front item from the deque. */
public int getFront() {
return isEmpty() ? -1 : arr[start];
}

/** Get the last item from the deque. */
public int getRear() {
return isEmpty() ? -1 : arr[end];
}

/** Checks whether the circular deque is empty or not. */
public boolean isEmpty() {
return len == 0;
}

/** Checks whether the circular deque is full or not. */
public boolean isFull() {
return len == k;
}
}

/**
* Your MyCircularDeque object will be instantiated and called as such:
* MyCircularDeque obj = new MyCircularDeque(k);
* boolean param_1 = obj.insertFront(value);
* boolean param_2 = obj.insertLast(value);
* boolean param_3 = obj.deleteFront();
* boolean param_4 = obj.deleteLast();
* int param_5 = obj.getFront();
* int param_6 = obj.getRear();
* boolean param_7 = obj.isEmpty();
* boolean param_8 = obj.isFull();
*/
}

• // OJ: https://leetcode.com/problems/design-circular-deque/
// Time: O(1) for all
// Space: O(K)
class MyCircularDeque {
vector<int> q;
int begin = 0, end = 0, k, cnt = 0;
public:
MyCircularDeque(int k) : q(k), k(k) {}
bool insertFront(int value) {
if (cnt == k) return false;
begin = (begin - 1 + k) % k;
q[begin] = value;
++cnt;
return true;
}
bool insertLast(int value) {
if (cnt == k) return false;
q[end] = value;
end = (end + 1) % k;
++cnt;
return true;
}
bool deleteFront() {
if (cnt == 0) return false;
begin = (begin + 1) % k;
--cnt;
return true;
}
bool deleteLast() {
if (cnt == 0) return false;
end = (end - 1 + k) % k;
--cnt;
return true;
}
int getFront() {
if (cnt == 0) return -1;
return q[begin];
}
int getRear() {
if (cnt == 0) return -1;
return q[(end - 1 + k) % k];
}
bool isEmpty() {
return cnt == 0;
}
bool isFull() {
return cnt == k;
}
};

• class MyCircularDeque(object):

def __init__(self, k):
"""
Initialize your data structure here. Set the size of the deque to be k.
:type k: int
"""
self.queue = []
self.size = k
self.front = 0
self.rear = 0

def insertFront(self, value):
"""
Adds an item at the front of Deque. Return true if the operation is successful.
:type value: int
:rtype: bool
"""
if not self.isFull():
self.queue.insert(0, value)
self.rear += 1
return True
else:
return False

def insertLast(self, value):
"""
Adds an item at the rear of Deque. Return true if the operation is successful.
:type value: int
:rtype: bool
"""
if not self.isFull():
self.queue.append(value)
self.rear += 1
return True
else:
return False

def deleteFront(self):
"""
Deletes an item from the front of Deque. Return true if the operation is successful.
:rtype: bool
"""
if not self.isEmpty():
self.queue.pop(0)
self.rear -= 1
return True
else:
return False

def deleteLast(self):
"""
Deletes an item from the rear of Deque. Return true if the operation is successful.
:rtype: bool
"""
if not self.isEmpty():
self.queue.pop()
self.rear -= 1
return True
else:
return False

def getFront(self):
"""
Get the front item from the deque.
:rtype: int
"""
if self.isEmpty():
return -1
else:
return self.queue[self.front]

def getRear(self):
"""
Get the last item from the deque.
:rtype: int
"""
if self.isEmpty():
return -1
else:
return self.queue[self.rear -1]

def isEmpty(self):
"""
Checks whether the circular deque is empty or not.
:rtype: bool
"""
return self.front == self.rear

def isFull(self):
"""
Checks whether the circular deque is full or not.
:rtype: bool
"""
return self.rear - self.front == self.size

# Your MyCircularDeque object will be instantiated and called as such:
# obj = MyCircularDeque(k)
# param_1 = obj.insertFront(value)
# param_2 = obj.insertLast(value)
# param_3 = obj.deleteFront()
# param_4 = obj.deleteLast()
# param_5 = obj.getFront()
# param_6 = obj.getRear()
# param_7 = obj.isEmpty()
# param_8 = obj.isFull()