Welcome to Subscribe On Youtube

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

641. Design Circular Deque

Level

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();
     */
    }
    
    ############
    
    class MyCircularDeque {
        private int[] q;
        private int front;
        private int size;
        private int capacity;
    
        /** Initialize your data structure here. Set the size of the deque to be k. */
        public MyCircularDeque(int k) {
            q = new int[k];
            capacity = 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 (!isEmpty()) {
                front = (front - 1 + capacity) % capacity;
            }
            q[front] = value;
            ++size;
            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;
            }
            int idx = (front + size) % capacity;
            q[idx] = value;
            ++size;
            return true;
        }
    
        /** Deletes an item from the front of Deque. Return true if the operation is successful. */
        public boolean deleteFront() {
            if (isEmpty()) {
                return false;
            }
            front = (front + 1) % capacity;
            --size;
            return true;
        }
    
        /** Deletes an item from the rear of Deque. Return true if the operation is successful. */
        public boolean deleteLast() {
            if (isEmpty()) {
                return false;
            }
            --size;
            return true;
        }
    
        /** Get the front item from the deque. */
        public int getFront() {
            if (isEmpty()) {
                return -1;
            }
            return q[front];
        }
    
        /** Get the last item from the deque. */
        public int getRear() {
            if (isEmpty()) {
                return -1;
            }
            int idx = (front + size - 1) % capacity;
            return q[idx];
        }
    
        /** Checks whether the circular deque is empty or not. */
        public boolean isEmpty() {
            return size == 0;
        }
    
        /** Checks whether the circular deque is full or not. */
        public boolean isFull() {
            return size == capacity;
        }
    }
    
    /**
     * 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:
        def __init__(self, k: int):
            """
            Initialize your data structure here. Set the size of the deque to be k.
            """
            self.q = [0] * k
            self.front = 0
            self.size = 0
            self.capacity = k
    
        def insertFront(self, value: int) -> bool:
            """
            Adds an item at the front of Deque. Return true if the operation is successful.
            """
            if self.isFull():
                return False
            if not self.isEmpty():
                self.front = (self.front - 1 + self.capacity) % self.capacity
            self.q[self.front] = value
            self.size += 1
            return True
    
        def insertLast(self, value: int) -> bool:
            """
            Adds an item at the rear of Deque. Return true if the operation is successful.
            """
            if self.isFull():
                return False
            idx = (self.front + self.size) % self.capacity
            self.q[idx] = value
            self.size += 1
            return True
    
        def deleteFront(self) -> bool:
            """
            Deletes an item from the front of Deque. Return true if the operation is successful.
            """
            if self.isEmpty():
                return False
            self.front = (self.front + 1) % self.capacity
            self.size -= 1
            return True
    
        def deleteLast(self) -> bool:
            """
            Deletes an item from the rear of Deque. Return true if the operation is successful.
            """
            if self.isEmpty():
                return False
            self.size -= 1
            return True
    
        def getFront(self) -> int:
            """
            Get the front item from the deque.
            """
            if self.isEmpty():
                return -1
            return self.q[self.front]
    
        def getRear(self) -> int:
            """
            Get the last item from the deque.
            """
            if self.isEmpty():
                return -1
            idx = (self.front + self.size - 1) % self.capacity
            return self.q[idx]
    
        def isEmpty(self) -> bool:
            """
            Checks whether the circular deque is empty or not.
            """
            return self.size == 0
    
        def isFull(self) -> bool:
            """
            Checks whether the circular deque is full or not.
            """
            return self.size == self.capacity
    
    
    # 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()
    
    ############
    
    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()
    
  • type MyCircularDeque struct {
    	q        []int
    	size     int
    	front    int
    	capacity int
    }
    
    func Constructor(k int) MyCircularDeque {
    	q := make([]int, k)
    	return MyCircularDeque{q, 0, 0, k}
    }
    
    func (this *MyCircularDeque) InsertFront(value int) bool {
    	if this.IsFull() {
    		return false
    	}
    	if !this.IsEmpty() {
    		this.front = (this.front - 1 + this.capacity) % this.capacity
    	}
    	this.q[this.front] = value
    	this.size++
    	return true
    }
    
    func (this *MyCircularDeque) InsertLast(value int) bool {
    	if this.IsFull() {
    		return false
    	}
    	idx := (this.front + this.size) % this.capacity
    	this.q[idx] = value
    	this.size++
    	return true
    }
    
    func (this *MyCircularDeque) DeleteFront() bool {
    	if this.IsEmpty() {
    		return false
    	}
    	this.front = (this.front + 1) % this.capacity
    	this.size -= 1
    	return true
    }
    
    func (this *MyCircularDeque) DeleteLast() bool {
    	if this.IsEmpty() {
    		return false
    	}
    	this.size -= 1
    	return true
    }
    
    func (this *MyCircularDeque) GetFront() int {
    	if this.IsEmpty() {
    		return -1
    	}
    	return this.q[this.front]
    }
    
    func (this *MyCircularDeque) GetRear() int {
    	if this.IsEmpty() {
    		return -1
    	}
    	return this.q[(this.front+this.size-1)%this.capacity]
    }
    
    func (this *MyCircularDeque) IsEmpty() bool {
    	return this.size == 0
    }
    
    func (this *MyCircularDeque) IsFull() bool {
    	return this.size == this.capacity
    }
    
    /**
     * Your MyCircularDeque object will be instantiated and called as such:
     * obj := Constructor(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();
     */
    
  • class MyCircularDeque {
        private vals: number[];
        private length: number;
        private size: number;
        private start: number;
        private end: number;
    
        constructor(k: number) {
            this.vals = new Array(k).fill(0);
            this.start = 0;
            this.end = 0;
            this.length = 0;
            this.size = k;
        }
    
        insertFront(value: number): boolean {
            if (this.isFull()) {
                return false;
            }
    
            if (this.start === 0) {
                this.start = this.size - 1;
            } else {
                this.start--;
            }
            this.vals[this.start] = value;
            this.length++;
            return true;
        }
    
        insertLast(value: number): boolean {
            if (this.isFull()) {
                return false;
            }
    
            this.vals[this.end] = value;
            this.length++;
            if (this.end + 1 === this.size) {
                this.end = 0;
            } else {
                this.end++;
            }
            return true;
        }
    
        deleteFront(): boolean {
            if (this.isEmpty()) {
                return false;
            }
    
            if (this.start + 1 === this.size) {
                this.start = 0;
            } else {
                this.start++;
            }
            this.length--;
            return true;
        }
    
        deleteLast(): boolean {
            if (this.isEmpty()) {
                return false;
            }
    
            if (this.end === 0) {
                this.end = this.size - 1;
            } else {
                this.end--;
            }
            this.length--;
            return true;
        }
    
        getFront(): number {
            if (this.isEmpty()) {
                return -1;
            }
    
            return this.vals[this.start];
        }
    
        getRear(): number {
            if (this.isEmpty()) {
                return -1;
            }
    
            if (this.end === 0) {
                return this.vals[this.size - 1];
            }
            return this.vals[this.end - 1];
        }
    
        isEmpty(): boolean {
            return this.length === 0;
        }
    
        isFull(): boolean {
            return this.length === this.size;
        }
    }
    
    /**
     * Your MyCircularDeque object will be instantiated and called as such:
     * var obj = new MyCircularDeque(k)
     * var param_1 = obj.insertFront(value)
     * var param_2 = obj.insertLast(value)
     * var param_3 = obj.deleteFront()
     * var param_4 = obj.deleteLast()
     * var param_5 = obj.getFront()
     * var param_6 = obj.getRear()
     * var param_7 = obj.isEmpty()
     * var param_8 = obj.isFull()
     */
    
    

All Problems

All Solutions