Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
The Standard Toolbox  ›  Lesson

deque and heapq

Deque and Heapq 16 minPush/pop either end in O(1), or always reach the smallest next in O(log n)
Your task
Write triage_order(patients): each patient is [priority, name], lower priority number is more urgent. Return the names in the order they should be seen — by priority, and by arrival order (their position in the list) on a tie. Example: triage_order([[2, "Asha"], [1, "Bea"], [2, "Cy"]]) -> ["Bea", "Asha", "Cy"].

deque and heapq

In short: collections.deque is a list built for pushing and popping either end in constant time — list.pop(0) shifts every remaining item and gets slow on a long list, deque.popleft() never does. heapq turns a plain list into a min-heap: heappush/heappop keep the smallest item always reachable in O(log n), which is how you build a priority queue without sorting after every change. A deque(maxlen=n) silently drops from the far end once it's full — useful for a bounded history, dangerous if you expected an error instead. Reach for a deque when you add/remove from both ends; reach for a heap when you always need "the smallest (or largest) next," not the whole thing sorted.

A deque as three cards in a row with appendleft/append arrows going in either end and popleft/pop arrows coming out either end, beside a small heap tree where 1 sits on top of 4 and 3, with heappop() pulling the top value off

Undo history for a text editor

An editor keeps the last few actions so Ctrl+Z has something to undo. A plain list works, but popping the oldest action off the front is slow once the list is long — every remaining item has to shift over one slot. deque avoids the shift:

python

A bounded history is even more useful — keep only the last 3 actions, automatically:

What does this print?
from collections import deque

history = deque(maxlen=3)
for action in ["type a", "type b", "type c", "type d"]:
    history.append(action)
print(list(history))

A hospital triage queue

Patients don't arrive in the order they should be seen — a 1 (most urgent) should jump ahead of a 2 that arrived first. heapq keeps the smallest priority number on top no matter what order things were pushed in:

python

heapq compares the whole tuple, so on a tied priority it looks at the next element to break the tie. That's fine for two numbers — it breaks the moment the second element isn't comparable, like two dicts:

What happens when you run this?
import heapq

heap = []
heapq.heappush(heap, (2, {"name": "Asha"}))
heapq.heappush(heap, (2, {"name": "Bea"}))
heapq.heappop(heap)

A running counter fixes it — ties now break by arrival order, and the payload can be anything:

python

Merge two sorted leaderboards

Two already-sorted lists need to become one sorted list — say, scores from two game servers. Sorting the combined list again throws away work you already paid for; heapq.merge combines sorted inputs in one pass without re-sorting:

python

heapq also has two shortcuts for "give me the extremes without sorting the whole list": nlargest(n, items) and nsmallest(n, items).

python

Quick practice

What does this print?
from collections import deque

dq = deque([2, 3, 4])
dq.appendleft(1)
dq.append(5)
print(dq.popleft(), dq.pop())
broken — fix it

This prints 5, not the smallest value in the list. Heapify it first.


🎯 Your turn

Write triage_order(patients). Each patient is [priority, name] — a lower number is more urgent. Return the names in the order they should be seen: by priority first, and by arrival order (their position in the list) for a tie.

  • triage_order([[2, "Asha"], [1, "Bea"], [2, "Cy"]]) → ["Bea", "Asha", "Cy"]
  • triage_order([]) → []

Hint: push (priority, index, name) onto a heap as you loop with enumerate, then heapq.heappop() everything off in order and collect the names.

Press ▶ Run and hit ✓ Check. ✅

Practice — level up

0/5 solved

Solve each in its own editor — Run to try, Check to grade. Stuck? Reveal a Hint, or the full Solution + walkthrough.

Warm-upRotate a list

Write rotate_list(items, k) that rotates items right by k positions (a negative k rotates left), using deque.rotate.

deque
DrillCheck a palindrome from both ends

Write is_palindrome_deque(s) using a deque: repeatedly compare and remove the front and back characters with popleft()/pop() until fewer than 2 remain. Return False the moment two compared characters differ.

deque
BuildThe kth smallest number

Write kth_smallest(nums, k) returning the kth smallest value in nums (k=1 is the smallest), using heapq.nsmallest instead of sorting the whole list.

heapq
BossMerge two sorted leaderboards

Write merge_leaderboards(a, b): a and b are already sorted ascending. Return one sorted list with everything from both, using heapq.merge instead of concatenating and re-sorting.

heapq
CapstoneThe k nearest points to home

Write nearest_k_points(points, k): points is a list of [x, y] pairs. Return the k points closest to (0, 0), nearest first, without computing a real square root. Use heapq.nsmallest with a key.

heapq
triage_order.py
Call the function you wrote — just like your app's frontend would. Edit the inputs and hit Call.
triage_order(patients) → listSort patients by priority (lower first), ties by arrival order.
try:
returned
No app map for this section yet.
Press Run to execute your code.
Press Check to run the tests for this lesson.