Keep only the largest k values by maintaining a small min-heap.

Algorithm

Steps

  1. Store the heap in an array.
  2. Compare parent and child indexes instead of building explicit tree nodes.
  3. Swap only when the heap order is violated.
  4. Print the deterministic final heap state for replay comparison.

Complexity

  • Time: O(n log k)
  • Space: O(k)
bounded heap For top-k largest values, a min-heap of size k keeps the current cutoff at the root.

Scala DSA Implementation

basic.scala
import scala.collection.mutable.ArrayBuffer
object Main {
  def listString(values: Seq[Int]): String = values.mkString("[", ", ", "]")
  def heapInsert(heap: ArrayBuffer[Int], value: Int): Unit = {
    heap += value
    var child = heap.length - 1
    while (child > 0) {
      val parent = (child - 1) / 2
      if (heap(parent) <= heap(child)) return
      val tmp = heap(parent); heap(parent) = heap(child); heap(child) = tmp
      child = parent
    }
  }
  def heapPop(heap: ArrayBuffer[Int]): Int = {
    val smallest = heap(0)
    heap(0) = heap.remove(heap.length - 1)
    var parent = 0
    var done = false
    while (!done) {
      val left = parent * 2 + 1
      val right = left + 1
      if (left >= heap.length) done = true
      else {
        var child = left
        if (right < heap.length && heap(right) < heap(left)) child = right
        if (heap(parent) <= heap(child)) done = true
        else { val tmp = heap(parent); heap(parent) = heap(child); heap(child) = tmp; parent = child }
      }
    }
    smallest
  }
  def main(args: Array[String]): Unit = { val heap = ArrayBuffer.empty[Int]; for (value <- List(5, 1, 9, 3, 7, 2)) { heapInsert(heap, value); if (heap.length > 3) heapPop(heap) }; println(listString(heap.sorted(Ordering.Int.reverse))) }
}

Implementation notes

  • The working heap is a Scala mutable ArrayBuffer[Int], starting from ArrayBuffer.empty[Int].
  • The helper functions keep it as a min-heap, so the smallest kept top-k value sits at index 0.
  • for (value <- List(5, 1, 9, 3, 7, 2)) considers values in that fixed order.
  • Each value is first passed through heapInsert(heap, value), which appends and sifts up using parent indexes.
  • The size bound is the literal 3: after each insert, if (heap.length > 3) heapPop(heap) removes the current minimum.
  • That means low values can still be inserted briefly; the trace for 2 ends back at [5, 7, 9] after the pop removes it.
  • The replayed heap states are [5], [1, 5], [1, 5, 9], [3, 5, 9], [5, 7, 9], then [5, 7, 9].
  • The heap array is not stored in sorted order, so heap.sorted(Ordering.Int.reverse) is used only for output, producing [9, 7, 5].

Output

[9, 7, 5]