0
0
DSA Typescriptprogramming

Why Heap Exists and What Sorted Array Cannot Do Efficiently in DSA Typescript - Why This Pattern

Choose your learning style9 modes available
Mental Model
A heap lets us quickly find and remove the smallest or largest item, which a sorted array can't do efficiently when we need to add or remove items often.
Analogy: Imagine a messy pile of papers where you want the most important one fast. A heap is like a special stack that always keeps the top paper the most important, so you grab it quickly. A sorted array is like a neat stack but adding or removing papers in the middle takes a lot of time.
Sorted array: [1, 3, 5, 7, 9]
Heap (min-heap):
      1
     / \
    3   5
   / \
  7   9
Dry Run Walkthrough
Input: Start with sorted array [1, 3, 5, 7, 9], then insert 2 and remove smallest element.
Goal: Show why inserting and removing smallest in a sorted array is slow, but fast in a heap.
Step 1: Insert 2 into sorted array by shifting elements to keep order
[1, 2, 3, 5, 7, 9]
Why: We must move elements to keep the array sorted, which takes time.
Step 2: Remove smallest element (1) by shifting all elements left
[2, 3, 5, 7, 9]
Why: Removing first element requires shifting all others, which is slow.
Step 3: Insert 2 into heap by adding at bottom and bubbling up
      1
     / \
    3   5
   / \  /
  7  9 2↑
Why: Heap inserts at bottom and moves up to keep heap order efficiently.
Step 4: Bubble up 2 to correct position in heap
      1
     / \
    2↑  5
   / \  /
  7  9 3
Why: We swap 2 with 3 to keep smallest on top without shifting whole structure.
Step 5: Remove smallest element (1) from heap by replacing root with last and bubbling down
      2↑
     / \
    3   5
   / \
  7   9
Why: Heap removes root and fixes order by bubbling down, avoiding full shifts.
Result:
Sorted array after insert and remove: [2, 3, 5, 7, 9]
Heap after insert and remove:
      2
     / \
    3   5
   / \
  7   9
Annotated Code
DSA Typescript
class MinHeap {
  heap: number[] = [];

  insert(val: number) {
    this.heap.push(val); // add at end
    this.bubbleUp(); // fix heap order
  }

  bubbleUp() {
    let idx = this.heap.length - 1;
    while (idx > 0) {
      let parentIdx = Math.floor((idx - 1) / 2);
      if (this.heap[parentIdx] <= this.heap[idx]) break;
      [this.heap[parentIdx], this.heap[idx]] = [this.heap[idx], this.heap[parentIdx]]; // swap
      idx = parentIdx; // move up
    }
  }

  removeMin() {
    if (this.heap.length === 0) return null;
    if (this.heap.length === 1) return this.heap.pop()!;
    const min = this.heap[0];
    this.heap[0] = this.heap.pop()!; // replace root with last
    this.bubbleDown(); // fix heap order
    return min;
  }

  bubbleDown() {
    let idx = 0;
    const length = this.heap.length;
    while (true) {
      let leftIdx = 2 * idx + 1;
      let rightIdx = 2 * idx + 2;
      let smallest = idx;

      if (leftIdx < length && this.heap[leftIdx] < this.heap[smallest]) {
        smallest = leftIdx;
      }
      if (rightIdx < length && this.heap[rightIdx] < this.heap[smallest]) {
        smallest = rightIdx;
      }
      if (smallest === idx) break;
      [this.heap[idx], this.heap[smallest]] = [this.heap[smallest], this.heap[idx]]; // swap
      idx = smallest; // move down
    }
  }

  print() {
    console.log(this.heap.join(' -> ') + ' -> null');
  }
}

// Sorted array insert and remove
let sortedArray = [1, 3, 5, 7, 9];
// Insert 2
let insertPos = sortedArray.findIndex(x => x > 2);
if (insertPos === -1) insertPos = sortedArray.length;
sortedArray.splice(insertPos, 0, 2);
// Remove smallest (first element)
sortedArray.shift();
console.log('Sorted Array:', sortedArray.join(' -> ') + ' -> null');

// Heap insert and remove
const heap = new MinHeap();
[1, 3, 5, 7, 9].forEach(x => heap.insert(x));
heap.insert(2);
heap.removeMin();
process.stdout.write('Heap: ');
heap.print();
this.heap.push(val); // add at end
insert new value at bottom of heap
this.bubbleUp(); // fix heap order
move inserted value up to maintain heap property
const min = this.heap[0];
store smallest value at root to return
this.heap[0] = this.heap.pop()!; // replace root with last
replace root with last element before bubbling down
this.bubbleDown(); // fix heap order
move root down to maintain heap property
let insertPos = sortedArray.findIndex(x => x > 2);
find position to insert 2 to keep array sorted
sortedArray.splice(insertPos, 0, 2);
insert 2 by shifting elements right
sortedArray.shift();
remove smallest element by shifting all left
OutputSuccess
Sorted Array: 2 -> 3 -> 5 -> 7 -> 9 -> null Heap: 2 -> 3 -> 5 -> 7 -> 9 -> null
Complexity Analysis
Time: O(n) for sorted array insert and remove because shifting elements takes time; O(log n) for heap insert and remove because bubbling up/down moves along tree height
Space: O(n) for both because they store all elements; heap uses array internally
vs Alternative: Heap is faster than sorted array for frequent insertions and removals because it avoids shifting many elements
Edge Cases
empty heap or array
removing smallest returns null or empty result without error
DSA Typescript
if (this.heap.length === 0) return null;
inserting smallest or largest value
heap bubbles up or array inserts at start or end correctly
DSA Typescript
let insertPos = sortedArray.findIndex(x => x > 2);
single element heap or array
removal returns that element and structure becomes empty
DSA Typescript
if (this.heap.length === 1) return this.heap.pop()!;
When to Use This Pattern
When you need to repeatedly get and remove the smallest or largest item quickly while also adding new items often, reach for the heap pattern because it keeps order efficiently without costly shifts.
Common Mistakes
Mistake: Trying to insert into a sorted array without shifting elements, causing order to break
Fix: Always find correct insert position and shift elements right to keep array sorted
Mistake: Not bubbling up or down in heap after insert or remove, breaking heap property
Fix: Always perform bubbleUp after insert and bubbleDown after remove to maintain heap order
Summary
A heap lets you quickly add items and get the smallest or largest without reordering everything.
Use a heap when you need fast access to min or max and frequent insertions or removals.
The key is that a heap keeps partial order with bubbling up/down, avoiding costly full shifts like in sorted arrays.