Katkat

Implement a Min-Heap with Insert and Remove-Min

Pony.AiSoftware Engineer · Technical Screen

Last updated

Implement a binary min-heap from scratch using a zero-indexed array, supporting insertion, peek, and extraction of the minimum element in logarithmic time.

Problem Statement

Implement a binary min-heap from scratch without using any built-in priority queue or heap libraries (such as Python's heapq). Your min-heap must store elements in a contiguous zero-indexed dynamic array and maintain the standard min-heap property: the value of each node must be less than or equal to the values of its children.

Implement the MinHeap class with the following methods:

  • __init__(): Initializes an empty min-heap.
  • insert(val: int) -> None: Adds an integer val into the heap.
  • extract_min() -> int | None: Removes and returns the smallest integer in the heap. If the heap is empty, returns None.
  • peek() -> int | None: Returns the smallest integer without removing it. If the heap is empty, returns None.
  • size() -> int: Returns the total number of elements currently stored in the heap.

Array Indexing Rules (0-indexed)

For an element at index i:

  • Parent: (i - 1) // 2 (for i > 0)
  • Left Child: 2 * i + 1
  • Right Child: 2 * i + 2

Example

heap = MinHeap()
heap.insert(5)
heap.insert(3)
heap.insert(8)
heap.insert(1)

heap.peek()        # returns 1
heap.extract_min() # returns 1
heap.extract_min() # returns 3
heap.size()        # returns 2
heap.insert(-2)
heap.extract_min() # returns -2
heap.extract_min() # returns 5
heap.extract_min() # returns 8
heap.extract_min() # returns None (heap is empty)

Constraints

  • Values inserted can be negative, zero, or positive: -10^9 <= val <= 10^9
  • Values may contain duplicates.
  • Up to 500,000 total calls across all methods.
  • insert and extract_min must run in O(log n) time.
  • peek and size must run in O(1) time.
  • Auxiliary space (excluding the array storing elements) must be O(1).

Edge Cases

  • Calling extract_min() or peek() on an empty heap should safely return None without raising an exception.
  • Removing elements until the heap transitions from size 1 to size 0.
  • Correctly comparing two children during sift-down when only the left child exists, or when child values are identical.

Hints

Hint 1

When inserting, place the new element at the end of the array and bubble (sift) it up toward the root as long as it is smaller than its parent.

Hint 2

When extracting the minimum, swap the root with the last element, pop the last element, and sift down the new root by repeatedly swapping with its smaller child.

Hint 3

Be careful with boundary conditions during sift-down: check if the right child exists before comparing children, and break early if the parent is already smaller than or equal to both children.

Follow-up questions

  • How would you implement a `heapify(arr)` constructor to initialize a heap from an unsorted list in `O(n)` time instead of `O(n log n)`?
  • How would you extend this design to support `decrease_key(index, new_val)` or `delete(index)` in `O(log n)` time?
  • How would you adapt this data structure to be thread-safe for concurrent read and write operations?