Circular Queue Implementation Using Array in DSA Java - Time & Space Complexity
We want to understand how the time taken by circular queue operations changes as the queue size grows.
Specifically, how fast can we add or remove items in a circular queue using an array?
Analyze the time complexity of the following enqueue and dequeue methods in a circular queue.
public boolean enqueue(int value) {
if ((rear + 1) % size == front) return false; // Queue full
rear = (rear + 1) % size;
arr[rear] = value;
return true;
}
public Integer dequeue() {
if (front == rear) return null; // Queue empty
front = (front + 1) % size;
return arr[front];
}
This code adds (enqueue) or removes (dequeue) elements in a circular queue using an array with wrap-around indexing.
Look for loops or repeated steps that affect time.
- Primary operation: Single step index update and assignment or retrieval.
- How many times: Each enqueue or dequeue runs once per call, no loops inside.
Each enqueue or dequeue does a fixed number of steps regardless of queue size.
| Input Size (n) | Approx. Operations per enqueue/dequeue |
|---|---|
| 10 | 4 steps |
| 100 | 4 steps |
| 1000 | 4 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: "Because the queue uses an array, enqueue or dequeue must scan or shift many elements, so it takes longer as the queue grows."
[OK] Correct: The circular queue uses index math to wrap around, so it never moves or scans all elements. Each operation only updates a few variables.
Understanding that circular queues provide constant time operations shows you know how to efficiently manage fixed-size buffers, a useful skill in many real-world systems.
"What if we changed the circular queue to a normal queue using an array without wrap-around? How would the time complexity of enqueue and dequeue 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 due to dequeues.Step 2: Circular queue advantage
A circular queue connects the end of the array back to the front, allowing reuse of empty slots and efficient space usage.Final Answer:
It efficiently utilizes the array space by reusing empty slots after dequeue operations. -> Option BQuick Check:
Space reuse = Advantage [OK]
- Thinking circular queue sorts elements
- Believing circular queue uses less memory
- Confusing data type flexibility with queue type
n with front and rear pointers?Solution
Step 1: Understand circular queue full condition
In a circular queue, the queue is full when the next position of rear (rear + 1 modulo n) is equal to front.Step 2: Apply modulo for wrap-around
Using modulo ensures the rear wraps to the start of the array, so full condition is front == (rear + 1) % n.Final Answer:
front == (rear + 1) % n -> Option AQuick Check:
Full if next rear equals front [OK]
- Using rear == (front + 1) % n (wrong direction)
- Checking front == rear (means empty, not full)
- Ignoring modulo wrap-around
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 each operation step-by-step
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 wraps to 0 (since (4+1)%5=0)Step 2: Final front and rear values
After last enqueue, front=1, rear=0Final Answer:
front = 1, rear = 0 -> Option DQuick Check:
Wrap rear with modulo, front moves on dequeue [OK]
- Not wrapping rear index after reaching array end
- Not updating front after dequeue
- Confusing initial front and rear values
void enqueue(int value) {
if ((rear + 1) % size == front) {
System.out.println("Queue is full");
return;
}
if (front == -1) front = 0;
rear = (rear + 1) % size;
queue[rear] = value;
}Solution
Step 1: Identify standard enqueue order
In standard circular queue implementations (wasting one slot to distinguish empty/full), the value is inserted at the current rear first: queue[rear] = value; then rear = (rear + 1) % size.Step 2: Problem with given code
This code updates rear first, then inserts. This causes false positives in the full check after dequeue operations make the queue empty, as front == (old rear + 1) % size, matching the full condition.Final Answer:
The rear pointer is updated before inserting the value. -> Option CQuick Check:
Standard order: insert then increment rear [OK]
- Confusing front and rear updates
- Misunderstanding full condition logic
- Ignoring initial empty queue setup
Solution
Step 1: Understand circular queue indexing
With front at 4 and rear at 2 in a size 6 queue, the queue wraps around the end of the array.Step 2: Identify occupied indices
Elements are from front (4) to end (5), then from start (0) to rear (2), so indices 4,5,0,1,2 hold elements.Final Answer:
The queue has elements from index 4 to 5 and 0 to 2. -> Option AQuick Check:
Wrap-around means elements split across array ends [OK]
- Assuming front > rear means empty queue
- Thinking queue is full when front > rear
- Ignoring wrap-around in circular queue
Ready to prove it?
Pass the test and this pattern moves unknown
