Python 3.11+
The examples use standard Python containers and syntax available in the supported browser runtime; Queue itself is taught as an interview abstraction.
Verify in Python docs(opens in a new tab)First-in-first-out structure for breadth-first traversal, scheduling, and ordered processing. This guide turns that contract into deliberate Python operations, interview invariants, and a runnable practice loop.
Recognize it when
Consider Queue when the prompt's constraints and required operations match this shape: First-in-first-out structure for breadth-first traversal, scheduling, and ordered processing.

Sign in to save your code and progress across devices. The lesson and problem statement remain public.
A queue preserves arrival order: the oldest pending item leaves first. That FIFO rule separates a queue from a stack and makes it the natural frontier for breadth-first exploration, scheduling, and stream processing. At every moment, queued items are discovered but not yet processed.
Use collections.deque: append enqueues on the right and popleft dequeues from the left, both in
O(1) time. A Python list’s pop(0) shifts every remaining reference and costs O(n). The
deque documentation(opens in a new tab)
also provides two-ended operations, but a queue deliberately uses only one input and one output end.
In breadth-first work, mark an item seen when enqueuing it, not when later removing it. Then each reachable item enters once. To preserve layers, capture the queue length before processing the current batch; newly discovered items belong to the next layer.
from collections import deque
def breadth_layers(adjacency, start):
queue = deque([start])
seen = {start}
layers = []
while queue:
layer = []
for _ in range(len(queue)):
node = queue.popleft()
layer.append(node)
for neighbor in adjacency[node]:
if neighbor not in seen:
seen.add(neighbor)
queue.append(neighbor)
layers.append(layer)
return layersImplement breadth_layers(adjacency, start). Return reachable nodes grouped by unweighted distance, marking each node seen when it is enqueued.
Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor
A fixed-capacity queue can reuse an array with head, tail, and size. Enqueue writes at tail
and advances modulo capacity; dequeue reads at head and advances the same way. When head equals
tail, size distinguishes empty from full. Every accepted operation remains O(1).
def simulate_circular_buffer(capacity, actions):
storage = [None] * capacity
head = tail = size = 0
output = []
for action in actions:
if action[0] == 'put':
if size < capacity:
storage[tail] = action[1]
tail = (tail + 1) % capacity
size += 1
elif size == 0:
output.append(None)
else:
output.append(storage[head])
head = (head + 1) % capacity
size -= 1
return outputImplement simulate_circular_buffer(capacity, actions). Accept puts while space remains and return values or None for each get in FIFO order.
Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor
Use a queue when arrival or graph distance determines processing order. Use a stack for nested or depth-first work, a priority queue when the smallest key must leave first, and a deque when both ends are meaningful. Sorting all pending work repeatedly is not a substitute for a priority queue.
list.pop(0) hides O(n) shifting inside every dequeue.Define what one queued item represents and why FIFO order matches the problem’s guarantee. State when items become seen, what is true before a dequeue, and whether the maximum frontier controls space. For a circular buffer, explain the meaning of all three counters before writing modulo arithmetic.
Advance a Circular Buffer(opens in a new tab) isolates wraparound state. Design Circular Queue(opens in a new tab) adds the full public API and persistent empty/full semantics.
Python 3.11+
The examples use standard Python containers and syntax available in the supported browser runtime; Queue itself is taught as an interview abstraction.
Verify in Python docs(opens in a new tab)Interview bounds depend on the stated representation, input model, and real Python operations.
| Operation | Average | Worst | Interview note |
|---|---|---|---|
| Core Queue workflow | O(a) | O(a) | A bounded FIFO can reuse fixed storage when head, tail, and size make full and empty states explicit. head identifies the oldest live value, tail identifies the next write slot, and size stays between zero and capacity. |
O(capacity) for the demonstrated Queue workflow.
These are the mistakes most likely to survive a happy-path example and fail a boundary case.
Placeholder code cannot preserve the Queue invariant or satisfy the public contract.
Prevent it: Implement the smallest complete transition and run the public tests before adding optimizations.
Avoid
def simulate_circular_buffer(capacity, actions):
passUse instead
def simulate_circular_buffer(capacity, actions):
storage = [None] * capacity
head = tail = size = 0
output = []
for action in actions:
if action[0] == 'put':
if size < capacity:
storage[tail] = action[1]
tail = (tail + 1) % capacity
size += 1
else:
if size == 0:
output.append(None)
else:
output.append(storage[head])
head = (head + 1) % capacity
size -= 1
return outputWhere you will hit this: Advance a Circular Buffer(opens in a new tab)
Evicts the oldest live value when full instead of ignoring the rejected put operation.
Prevent it: Keep this invariant visible while editing: State the precise Queue invariant before coding and preserve it after every update, traversal step, or recursive return.
Avoid
def simulate_circular_buffer(capacity, actions):
storage = []
output = []
for action in actions:
if action[0] == 'put':
storage.append(action[1])
if len(storage) > capacity:
storage.pop(0)
else:
output.append(storage.pop(0) if storage else None)
return outputUse instead
def simulate_circular_buffer(capacity, actions):
storage = [None] * capacity
head = tail = size = 0
output = []
for action in actions:
if action[0] == 'put':
if size < capacity:
storage[tail] = action[1]
tail = (tail + 1) % capacity
size += 1
else:
if size == 0:
output.append(None)
else:
output.append(storage[head])
head = (head + 1) % capacity
size -= 1
return outputWhere you will hit this: Advance a Circular Buffer(opens in a new tab)
Handle empty state, duplicate values, aliasing, and serialization boundaries explicitly in tests.
Prevent it: Account for every slice, copy, sort, membership test, and container mutation before claiming O(a).
Avoid
def simulate_circular_buffer(capacity, actions):
storage = []
output = []
for action in actions:
if action[0] == 'put':
storage.append(action[1])
if len(storage) > capacity:
storage.pop(0)
else:
output.append(storage.pop(0) if storage else None)
return outputUse instead
def simulate_circular_buffer(capacity, actions):
storage = [None] * capacity
head = tail = size = 0
output = []
for action in actions:
if action[0] == 'put':
if size < capacity:
storage[tail] = action[1]
tail = (tail + 1) % capacity
size += 1
else:
if size == 0:
output.append(None)
else:
output.append(storage[head])
head = (head + 1) % capacity
size -= 1
return outputWhere you will hit this: Design Circular Queue(opens in a new tab)
Official Python documentation supports language behavior. Canonical problem pages provide additional practice context.
python-docs · checked 2026-07-12