Android & iPhone apps are coming soon. Log in for a plan and reminders made for you →

IntermediateMath for DSAUsed everywhere

1 + 2 + 4 + … + n < 2n

Doubling sizes add up to less than twice the last one. That's why dynamic arrays are O(1) per append and a full tree has 2ʰ⁺¹ − 1 nodes.

The idea

Each power of two is one more than the sum of all the smaller ones: 1 + 2 + 4 = 7 = 8 − 1. So 1 + 2 + … + 2ᵏ = 2ᵏ⁺¹ − 1, less than twice the last term.

A dynamic array (Python list, ArrayList) doubles when full and copies everything. Copies cost 1 + 2 + 4 + … + n < 2n in total, so n appends cost O(n): O(1) each on average. A perfect binary tree of height h has 1 + 2 + … + 2ʰ = 2ʰ⁺¹ − 1 nodes, half of them leaves.

Worked example

Appending 16 items to a list that starts with room for 1

  1. Resizes copy 1, 2, 4 and 8 items: 15 copies.
  2. Plus 16 writes. 31 operations for 16 appends: under 2 per append.

In code (Python)

def resize_copies(n):
    capacity, copies = 1, 0
    for size in range(1, n + 1):
        if size > capacity:
            copies += capacity     # copy everything into a twice-as-big array
            capacity *= 2
    return copies

# resize_copies(16) == 15; always under 2n

Total work for n doubling steps is O(n).

How to spot it

  • Anything that doubles: dynamic arrays, tree levels, repeated squaring, merge sort's levels.

Common mistakes

  • Calling append O(n) because a single resize is O(n): the average is O(1).
  • Forgetting a complete tree's last level holds about half its nodes.

Where it comes up

Go further