You Don’t Need to Memorize Heap Code. Understand These 5 Ideas Instead.

A beginner-friendly guide to heaps, priority queues, heapify, and the O(log n) idea behind them

You Don’t Need to Memorize Heap Code. Understand These 5 Ideas Instead.

Imagine you are building a food delivery app.

There are hundreds of orders waiting to be processed:

Order A → 25 minutes
Order B → 8 minutes
Order C → 15 minutes
Order D → 3 minutes

Now your system asks:

Which order should I process next?

You could look through every order and find the one with the smallest time.

But then another order arrives.

And another.

And another.

Every time you need the smallest value, you have to search again.

This sounds simple with four orders. But when the number of items keeps growing and you repeatedly need the smallest, largest, or highest-priority item, scanning everything again starts becoming expensive.

This is where heaps become useful.

And honestly, when I first learned heaps, the code looked more complicated than the idea actually was.

There are only a few ideas you really need to understand.

Once those ideas click, the code becomes much easier to remember.


1. A Heap Is Not a Sorted Array

This is probably the first thing that confused me about heaps.

If I tell you:

“A min heap always gives you the minimum element.”

You might imagine something like this:

[1, 2, 3, 4, 5, 6, 7]

But a heap does not need to be completely sorted.

A valid min heap can look like this:

          1
        /   \
       3     2
      / \   / \
     8   5 7   4

Look carefully.

Is this sorted? No.

But is it a min heap? Yes.

Why?

Because the important rule is:

Every parent must be smaller than or equal to its children.

For example:

        1
       / \
      3   2

1 is smaller than both 3 and 2.

Then:

       3
      / \
     8   5

3 is smaller than both 8 and 5.

And:

       2
      / \
     7   4

2 is smaller than both 7 and 4.

That’s enough.

The entire tree doesn’t need to be sorted.

For a Min Heap

parent <= children

For a Max Heap

parent >= children

So a max heap could look like:

          9
        /   \
       7     8
      / \   / \
     3   5 2   6

The largest value is always at the top.

And that’s the first big idea:

A heap doesn’t completely sort your data. It only keeps enough order to quickly access the minimum or maximum.


2. Why Can We Get the Minimum in O(1)?

Now the interesting part.

Look at our min heap again:

          1
        /   \
       3     2
      / \   / \
     8   5 7   4

Where is the smallest value?

At the root.

So if we store this tree in an array:

[1, 3, 2, 8, 5, 7, 4]

the minimum is simply:

heap[0]

That’s it. No searching. No loop.No sorting.

Therefore: Peek minimum → O(1)

This operation is often called peek.

We are asking:

“What is the minimum value?”

but we are not removing it.


3. How Can a Tree Live Inside an Array?

This is another important idea.

You might be wondering:

“If a heap is a binary tree, why are we talking about arrays?”

Because a heap is usually represented using an array.

Consider this tree:

          1
        /   \
       3     2
      / \   / \
     8   5 7   4

We can represent it as:

[1, 3, 2, 8, 5, 7, 4]

There are no pointers.

  • No left property.

  • No right property.

We calculate where the children are using the index.

For a zero-indexed array:

leftChild  = 2 * i + 1
rightChild = 2 * i + 2
parent     = Math.floor((i - 1) / 2)

For example, suppose:

i = 1

The value at index 1 is:

3

Its left child:

2 * 1 + 1 = 3

Index 3 contains:

8

Its right child:

2 * 1 + 2 = 4

Index 4 contains:

5

So:

          1
        /   \
       3     2
      / \
     8   5

can be navigated just by calculating indexes.

That’s a really useful trick.


4. What Happens When We Add a New Element?

Let’s say our min heap currently looks like this:

          1
        /   \
       3     2
      / \   / \
     8   5 7   4

Now we want to insert:

0

We first put it at the next available position:

          1
        /   \
       3     2
      / \   / \
     8   5 7   4
    /
   0

But we have a problem.

0 is smaller than its parent 8.

So they swap:

          1
        /   \
       3     2
      / \   / \
     0   5 7   4
    /
   8

Still not correct. 0 is smaller than its new parent 3.

Swap again:

          1
        /   \
       0     2
      / \   / \
     3   5 7   4
    /
   8

And again, 0 is smaller than 1.

So:

          0
        /   \
       1     2
      / \   / \
     3   5 7   4
    /
   8

Now the heap property is restored.

This process is usually called sift up or bubble up.

The important thing is that we didn’t move through every element.

We only moved along one path from the bottom toward the root.

That’s where O(log n) comes from.


5. Why Is Push O(log n)?

A heap is a roughly balanced binary tree.

Imagine the number of nodes at each level:

Level 0 → 1 node
Level 1 → 2 nodes
Level 2 → 4 nodes
Level 3 → 8 nodes
Level 4 → 16 nodes

The number of nodes approximately doubles at every level.

So as the number of elements grows, the height of the tree grows logarithmically.

Height ≈ log₂(n)

When we insert an element, the worst thing that can happen is that it travels from the bottom all the way to the root.

Therefore:

Heap push → O(log n)

This is one of the most important things to remember about heaps.

But don’t just memorize it.

Remember why:

A new element only travels along the height of the heap.


6. What Happens When We Remove the Minimum?

Now let’s go in the other direction.

Suppose we have:

          1
        /   \
       3     2
      / \   / \
     8   5 7   4

We want to remove the minimum.

The minimum is: 1

So we remove it.

But now the root is empty.

What should go there?

A common approach is to take the last element: 4

and put it at the root.

          4
        /   \
       3     2
      / \   /
     8   5 7

But this isn’t a valid min heap.

4 is bigger than 2.

So we compare it with its children and swap it with the smaller child.

          2
        /   \
       3     4
      / \   /
     8   5 7

Now the heap property is restored.

This process is called sift down.

Again, notice what happened.

We didn’t scan the entire tree.

We only followed one path downward.

So:

Heap pop → O(log n)

7. The Four Heap Operations You Should Know

At this point, most of the important complexity becomes intuitive.

The Four Heap Operations You Should Know

The first three are fairly intuitive.

But the last one is where things get interesting.


8. Heapify: Why Is It O(n)?

Suppose you already have this array:

const nums = [5, 3, 8, 1, 2, 7, 4];

It isn’t a heap yet.

One obvious approach would be:

Take 5 → push into heap
Take 3 → push into heap
Take 8 → push into heap
Take 1 → push into heap
...

If we insert n elements and every insertion can cost O(log n):

n × O(log n) = O(n log n)

But there is another way.

We can build the heap bottom-up.

We start from the last non-leaf node and repeatedly perform sift down.

The surprising result is:

Heapify → O(n)

This is one of those complexities that looks strange when you first see it.

You might naturally think:

“How can building a heap be faster than inserting all the elements one by one?”

The reason is that most nodes are near the bottom of the tree.

And nodes near the bottom have very little distance to travel.

Only a small number of nodes are high enough to travel many levels.

So the total work adds up to O(n).

You don’t need to memorize the mathematical proof to start using heaps.

Just remember this distinction:

Build heap using repeated push → O(n log n)
Build heap using heapify       → O(n)

That’s a useful interview detail.


9. Heap vs Priority Queue

Now we can finally connect the two terms that are often used together:

Heap and Priority Queue.

A priority queue is basically a data structure where the item with the highest priority gets processed first.

For example:

Emergency patient → Priority 1
High priority     → Priority 2
Normal patient    → Priority 3

The smaller number represents higher priority.

So we want:

Priority 1
   ↓
Priority 2
   ↓
Priority 3

A min heap is perfect for this.

We can store:

[1, "Emergency patient"]
[2, "High priority"]
[3, "Normal patient"]

The heap cares about the priority:

1

but we keep the associated information:

"Emergency patient"

This idea becomes extremely useful in coding problems.


10. Heaps Can Store More Than Just Numbers

This is something I would pay attention to if you’re preparing for coding interviews.

A heap doesn’t have to contain:

1
2
3
4

You can store multiple pieces of information together.

For example:

[
  [1, "Order D"],
  [8, "Order B"],
  [15, "Order C"],
  [25, "Order A"]
]

Here the first value is the priority.

The second value is the actual data.

So the heap can answer:

“Give me the order with the smallest delivery time.”

and return:

[1, "Order D"]

This pattern shows up frequently in problems involving:

  • Top K elements

  • frequencies

  • scheduling

  • shortest paths

  • merging sorted data

  • priority-based processing

Once you recognize that pattern, many heap problems become much less scary.


11. Heap Sort Is Basically “Keep Taking the Minimum”

Now that we understand pop, heap sort becomes surprisingly simple.

Imagine:

[5, 2, 8, 1, 3]

First, turn it into a min heap.

Then:

Pop → 1
Pop → 2
Pop → 3
Pop → 5
Pop → 8

The values come out in sorted order.

The idea is:

Unsorted array
      ↓
   Heapify
      ↓
   Min Heap
      ↓
  Pop minimum
      ↓
  Pop minimum
      ↓
  Pop minimum
      ↓
    Sorted

There are n elements.

Each pop costs O(log n).

So:

n × O(log n) = O(n log n)

Heap sort therefore has:

Time  → O(n log n)

A straightforward implementation that creates another array uses:

Space → O(n)

There are more advanced in-place versions that can achieve constant extra space, but the basic version is much easier to understand first.


12. Min Heap vs Max Heap

Everything we’ve discussed so far has been about a min heap.

But sometimes we want the largest value quickly.

That’s when we use a max heap.

Min Heap

        1
      /   \
     3     2
    / \
   8   5

Smallest value is at the root.

peek() → 1

Max Heap

8
      /   \
     5     7
    / \
   3   2

Largest value is at the root.

peek() → 8

The operations are basically the same.

The only difference is the comparison rule.

Min Heap:
parent <= children

Max Heap:
parent >= children

13. What About JavaScript?

This is where things get slightly annoying.

Some languages provide a ready-made priority queue or heap implementation.

But JavaScript doesn’t give you a simple built-in MinHeap class that you can use directly like:

const heap = new MinHeap();

So for DSA problems, it’s useful to understand how to implement one yourself.

The basic structure looks like:

class MinHeap {
  constructor() {
    this.heap = [];
  }
  peek() {
    return this.heap[0];
  }
  push(value) {
    // Add value at the end
    // Then sift it up
  }
  pop() {
    // Remove the root
    // Move the last value to the root
    // Then sift it down
  }
}

The code is not the part I’d try to memorize first.

I’d memorize the two movements:

INSERT
   ↓
Put at the bottom
   ↓
Sift UP

and:

REMOVE ROOT
   ↓
Move last element to root
   ↓
Sift DOWN

Once these two ideas are clear, implementing a heap becomes much easier.


14. One More Trick: Turning a Min Heap Into a Max Heap

Sometimes the heap implementation you’re using only supports a min heap.

For example, Python’s heapq is based on a min heap.

But what if you need a max heap?

A common trick is to store negative values.

Suppose you want:

10
7
5
2

With a min heap, store:

-10
-7
-5
-2

The smallest negative value is:

-10

which corresponds to the largest original value:

10

So when you remove it:

const largest = -heapPop();

It feels a little weird at first.

But the idea is simple:

Negating the numbers reverses their ordering.


15. The Complexity Cheat Sheet

If you’re preparing for interviews, this is the table I’d keep somewhere nearby:

The Complexity Cheat Sheet

But don’t just memorize this table.

Try to remember the reason.

Why is peek O(1)?

Because the answer is at the root.

Why is push O(log n)?

Because the new element may travel up the height of the tree.

Why is pop O(log n)?

Because the replacement element may travel down the height of the tree.

Why is heapify O(n)?

Because we build the heap bottom-up, and most nodes don’t need to move very far.

That reasoning is much more useful than memorizing six complexity numbers.


So What Are the 5 Ideas You Actually Need to Remember?

If I had to forget all the heap code and keep only five things, these would be it.

1. A heap is not a sorted array

It only maintains a relationship between parents and children.

Min Heap → parent <= children
Max Heap → parent >= children

2. The root gives you the answer

Min Heap → minimum at root
Max Heap → maximum at root

That’s why peek is O(1).

3. Push means “sift up”

Add at bottom
      ↓
Compare with parent
      ↓
Swap if necessary
      ↓
Repeat

That’s O(log n).

4. Pop means “sift down”

Remove root
      ↓
Move last element to root
      ↓
Compare with children
      ↓
Swap with appropriate child
      ↓
Repeat

That’s also O(log n).

5. Heapify builds a heap in O(n)

Don’t confuse:

n pushes → O(n log n)

with:

heapify → O(n)

The Question I’d Ask You in an Interview

Suppose an interviewer gives you:

[7, 2, 9, 1, 5, 3]

and asks:

“I need to repeatedly get the smallest number, remove it, and then get the next smallest number. What data structure would you use?”

You might be tempted to say:

“I’ll sort the array.”

And sorting can certainly work.

But now imagine new numbers keep arriving:

Get minimum
Remove it
New number arrives
Get minimum
Remove it
Another number arrives...

Now a heap starts making much more sense.

That’s the real value of learning data structures.

Not:

“Which data structure should I memorize for this question?”

But:

“What operation do I need to perform repeatedly, and which data structure makes that operation cheap?”

That’s the mindset I would carry into a coding interview.


Final Thoughts

The first time you see heap code, it can look unnecessarily complicated.

There are indexes like:

2 * i + 1
2 * i + 2
Math.floor((i - 1) / 2)

Then there is siftUp.

  • Then siftDown.

  • Then heapify.

  • Then priority queues.

  • Then tuples.

It feels like there is a lot to memorize.

But once you step back, the whole thing is built around one simple idea:

Keep the most important element at the top, without fully sorting everything.

For a min heap, that important element is the smallest.

For a max heap, it’s the largest.

Everything else — push, pop, peek, heapify, and even priority queues—is built around maintaining that property.

And that’s probably the biggest lesson I take from heaps:

Don’t start by memorizing the implementation.

Start by asking:

What problem is this data structure solving?

Once you understand that, the code starts looking much less mysterious.

And the next time you see a coding problem ask


From Tech By Neha Gupta

  • 👏 Enjoyed the article? Don’t forget to leave a clap.

  • 💬 Have thoughts or questions? Share them in the comments.