Implement a Min-Priority Queue Without a Library Heap
AmazonSoftware Engineer · OnsiteLast updated
Tests implementation of a binary min-heap from scratch, including array-based representation, sift-up, and sift-down operations, without relying on built-in priority queue libraries.
Description
Design a min-priority queue data structure from scratch without using any built-in heap or priority queue libraries (such as Python's heapq, Java's PriorityQueue, or C++'s std::priority_queue).
The priority queue stores integers, supports duplicate values, and must provide standard priority queue operations with optimal time complexities.
Implement the MinPriorityQueue class with the following methods:
push(val: int) -> None: Inserts integervalinto the priority queue.peek() -> int | None: Returns the minimum element currently in the queue without removing it. If the queue is empty, returnsNone.pop() -> int | None: Removes and returns the minimum element from the queue. If the queue is empty, returnsNone.size() -> int: Returns the current number of elements stored in the queue.
Interface
class MinPriorityQueue:
def __init__(self):
pass
def push(self, val: int) -> None:
pass
def peek(self) -> int | None:
pass
def pop(self) -> int | None:
pass
def size(self) -> int:
pass
Example
pq = MinPriorityQueue()
pq.push(5)
pq.push(3)
pq.push(8)
pq.push(3) # duplicates are supported
print(pq.peek()) # returns 3
print(pq.size()) # returns 4
print(pq.pop()) # returns 3
print(pq.pop()) # returns 3
print(pq.pop()) # returns 5
print(pq.size()) # returns 1
print(pq.pop()) # returns 8
print(pq.pop()) # returns None (queue is empty)
print(pq.peek()) # returns None
Constraints
- Total operations called across
push,peek,pop, andsize: up to2 * 10^5. - Values inserted:
-10^9 <= val <= 10^9. pushmust run inO(log n)time.popmust run inO(log n)time.peekandsizemust run inO(1)time.
Hints
Hint 1
Represent the binary heap as a 0-indexed dynamic array where the parent of node index i is at (i - 1) // 2, and its children are at 2 * i + 1 and 2 * i + 2.
Hint 2
For push, append the new element to the end of the array and 'sift up' by repeatedly swapping it with its parent while it is smaller than the parent.
Hint 3
For pop, swap the root with the last element, remove the last element, and 'sift down' the new root by repeatedly swapping it with its smaller child.
Follow-up questions
- How would you implement an in-place build_heap (or heapify) method that accepts an array of n elements and runs in O(n) time instead of O(n log n)?
- How would you extend this class to support arbitrary object types with a custom comparator or key function?
- How would you make this priority queue thread-safe for concurrent read and write operations in a multi-threaded environment?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.