Double Ended Queue Deque in DSA C# - Time & Space Complexity
We want to understand how fast operations on a double ended queue (deque) run as the number of items grows.
Specifically, how adding or removing items from either end changes with size.
Analyze the time complexity of the following code snippet.
public class SimpleDeque
{
private LinkedList<int> items = new LinkedList<int>();
public void AddFront(int value) => items.AddFirst(value);
public void AddBack(int value) => items.AddLast(value);
public int RemoveFront() { var val = items.First.Value; items.RemoveFirst(); return val; }
public int RemoveBack() { var val = items.Last.Value; items.RemoveLast(); return val; }
}
This code shows adding and removing items from both ends of a deque using a linked list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Adding or removing nodes at the start or end of the linked list.
- How many times: Each operation happens once per call, no loops inside these methods.
Adding or removing from either end takes the same small amount of work no matter how many items are in the deque.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 1 operation per add or remove |
| 100 | 1 operation per add or remove |
| 1000 | 1 operation per add or remove |
Pattern observation: The work stays the same no matter how big the deque grows.
Time Complexity: O(1)
This means adding or removing from either end takes a constant amount of time regardless of deque size.
[X] Wrong: "Removing from the back takes longer because you have to look through all items."
[OK] Correct: Using a linked list, the deque keeps a direct pointer to the last item, so removal is quick without searching.
Knowing that deque operations run in constant time shows you understand efficient data structures for flexible queues.
"What if we used an array instead of a linked list? How would the time complexity of adding or removing from the front change?"
Practice
Solution
Step 1: Understand the definition of Deque
A Deque allows insertion and deletion at both front and rear ends, unlike a queue or stack.Step 2: Compare with other data structures
Queue restricts insertion to rear and deletion from front; stack restricts both to one end.Final Answer:
A data structure where elements can be added or removed from both ends -> Option AQuick Check:
Deque = double-ended queue [OK]
- Confusing deque with stack or queue
- Thinking deque allows random access
- Assuming insertion only at one end
Solution
Step 1: Recall C# standard library support for Deque
C# does not have a built-in Deque class, but LinkedList can be used as a deque.Step 2: Analyze options
Deque<int> dq = new Deque<int>(); is invalid as Deque class does not exist; Queue<int> dq = new Queue<int>(); is a queue, not deque; List<int> dq = new List<int>(); is a list, not deque.Final Answer:
LinkedList<int> dq = new LinkedList<int>(); -> Option AQuick Check:
LinkedList supports deque operations [OK]
- Trying to use non-existent Deque class
- Using Queue which is single-ended
- Using List which lacks efficient front operations
var dq = new LinkedList<int>(); dq.AddLast(10); dq.AddFirst(20); dq.AddLast(30); dq.RemoveFirst(); foreach(var item in dq) Console.Write(item + " ");
Solution
Step 1: Trace the additions to the deque
Added 10 at last: [10]; Added 20 at first: [20, 10]; Added 30 at last: [20, 10, 30]Step 2: Remove first element
RemoveFirst removes 20; deque becomes [10, 30]Step 3: Print elements
Output is "10 30 "Final Answer:
10 30 -> Option DQuick Check:
After RemoveFirst, deque = 10 30 [OK]
- Confusing AddFirst and AddLast positions
- Forgetting RemoveFirst removes front element
- Assuming RemoveFirst removes last element
var dq = new LinkedList<int>(); dq.AddFirst(5); dq.RemoveLast(); dq.RemoveLast(); Console.WriteLine(dq.Count);
Solution
Step 1: Trace the operations on deque
Added 5 at front: deque = [5]; RemoveLast removes 5: deque = []Step 2: Second RemoveLast on empty deque
Calling RemoveLast on empty LinkedList throws InvalidOperationExceptionFinal Answer:
InvalidOperationException at second RemoveLast call -> Option BQuick Check:
Removing from empty deque throws exception [OK]
- Assuming RemoveLast on empty deque does nothing
- Expecting output 0 instead of exception
- Confusing compile-time and runtime errors
var dq = new LinkedList<int>(); // Fill in operations below
Solution
Step 1: Add urgent tasks to front and normal tasks to rear
Urgent task 1: AddFirst(1); Normal task 2: AddLast(2); Urgent task 3: AddFirst(3)Step 2: Remove one task from front
RemoveFirst removes the front urgent task 3Final Answer:
dq.AddFirst(1); dq.AddLast(2); dq.AddFirst(3); dq.RemoveFirst(); -> Option CQuick Check:
Urgent front, normal rear, remove front [OK]
- Mixing AddFirst and AddLast for task priority
- Removing from wrong end
- Incorrect order of operations
Ready to prove it?
Pass the test and this pattern moves unknown
