Circular Queue Implementation Using Array in DSA Go - Time & Space Complexity
We want to understand how fast operations like adding or removing items work in a circular queue using an array.
How does the time needed change as the queue gets bigger?
Analyze the time complexity of the following code snippet.
func (q *CircularQueue) Enqueue(value int) bool {
if (q.rear+1)%q.size == q.front {
return false // Queue is full
}
q.rear = (q.rear + 1) % q.size
q.array[q.rear] = value
return true
}
func (q *CircularQueue) Dequeue() (int, bool) {
if q.front == q.rear {
return 0, false // Queue is empty
}
q.front = (q.front + 1) % q.size
return q.array[q.front], true
}
This code adds (Enqueue) and removes (Dequeue) items in a circular queue using an array with fixed size.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Single step index update and assignment or retrieval in array.
- How many times: Each operation runs once per call, no loops or recursion inside.
Each enqueue or dequeue does a fixed number of steps regardless of queue size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 5 steps |
| 100 | 5 steps |
| 1000 | 5 steps |
Pattern observation: The number of steps stays the same no matter how big the queue is.
Time Complexity: O(1)
This means adding or removing an item takes the same short time no matter how many items are in the queue.
[X] Wrong: "Enqueue or Dequeue takes longer as the queue gets full or empty."
[OK] Correct: The operations only update indexes and access one array spot, so time does not grow with queue size.
Knowing that circular queue operations run in constant time shows you understand efficient data handling, a key skill in many coding tasks.
"What if we used a linked list instead of an array for the circular queue? How would the time complexity change?"
Practice
Solution
Step 1: Understand linear queue limitation
In a linear queue using an array, once the rear reaches the end, no more elements can be added even if there are empty slots at the front.Step 2: Circular queue advantage
A circular queue connects the end of the array back to the front, allowing reuse of empty slots freed by dequeued elements.Final Answer:
It efficiently uses the available space by reusing freed slots. -> Option BQuick Check:
Space reuse = Advantage [OK]
- Thinking circular queue increases array size
- Believing it sorts elements automatically
- Confusing data type flexibility with queue type
n with front and rear indices?Solution
Step 1: Understand full condition in circular queue
The queue is full when the next position of rear (circularly) equals front.Step 2: Apply modulo for circular increment
Using modulonensures wrap-around, so(rear + 1) % n == frontmeans full.Final Answer:
if (rear + 1) % n == front -> Option DQuick Check:
Full condition uses modulo wrap [OK]
- Checking rear == front means empty, not full
- Using rear == n - 1 ignores circular wrap
- Confusing front == -1 as full condition
enqueue(10), enqueue(20), enqueue(30), dequeue(), enqueue(40), enqueue(50), enqueue(60)What will be the values of front and rear after these operations?
Solution
Step 1: Trace enqueue and dequeue operations
Start: front = -1, rear = -1
enqueue(10): front=0, rear=0
enqueue(20): rear=1
enqueue(30): rear=2
dequeue(): front=1 (removes 10)
enqueue(40): rear=3
enqueue(50): rear=4
enqueue(60): rear=(4+1)%5=0 (wraps around)Step 2: Final front and rear values
front = 1, rear = 0 after last enqueue.Final Answer:
front = 1, rear = 0 -> Option AQuick Check:
Wrap-around rear = 0, front moved after dequeue [OK]
- Not wrapping rear index after reaching end
- Forgetting to update front after dequeue
- Assuming front stays at -1 after first enqueue
func enqueue(q []int, front *int, rear *int, n int, value int) {
if (*rear+1)%n == *front {
fmt.Println("Queue is full")
return
}
if *front == -1 {
*front = 0
}
*rear = (*rear + 1) % n
q[*rear] = value
}Solution
Step 1: Check handling of empty queue
The code updates front to 0 only if front == -1, handling the initial empty state correctly.Step 2: Issue after full dequeues
After dequeuing all elements, dequeue updates front = (front + 1) % n, making (*rear + 1) % n == *front true, falsely detecting full. Enqueue fails to update/reset front for subsequent empty states.Final Answer:
The front pointer is not updated when queue is empty. -> Option CQuick Check:
Handle non-initial empty by resetting front [OK]
- Confusing full condition with rear == front
- Overlooking empty queue handling after dequeues
- Thinking slice passing causes the issue
Solution
Step 1: Understand initial state and full condition
Array size n=6, front=4, rear=2 (5 elements occupied, 1 free). Full: (rear + 1) % 6 == front.Step 2: Simulate each option
Only D causes final full state:
dequeue: front=5, rear=2 (4 elem)
enqueue: rear=3 (5 elem)
enqueue: rear=4 (6 elem, now full since (4+1)%6=5==front)
enqueue: full detected, no change. Final: front=5, rear=4 full.
Others end not full.Final Answer:
dequeue, enqueue, enqueue, enqueue -> Option AQuick Check:
Simulate steps to check final full condition [OK]
- Assuming enqueue always fills queue immediately
- Ignoring circular wrap in index calculations
- Not updating front on dequeue
Ready to prove it?
Pass the test and this pattern moves unknown
