Skip to content

Minimum Operations to Reduce N to 0 Using Powers of 2 ​

Problem Statement ​

Given a non-negative integer n, in each step you can add or subtract any power of 2 (i.e., 2^k for some k >= 0). Return the minimum number of operations needed to reduce n to 0.

Example 1:

Input: n = 39
Output: 3
Explanation: 39 = 32 + 4 + 2 + 1 (binary 100111). You can reach 0 in 3 ops:
  39 + 1 = 40       (binary 101000)
  40 - 8 = 32       (binary 100000)
  32 - 32 = 0

Example 2:

Input: n = 54
Output: 3
Explanation: 54 = 110110 in binary. One optimal path:
  54 - 2 = 52       (110100)
  52 + 4 = 56       (111000)
  56 - 8 = 48... no, better:
  54 + 2 = 56 (111000), 56 - 8 = 48 (110000), 48 - 16 = 32, 32 - 32 = 0 is 4 ops.
  Actual: 54 = 64 - 8 - 2 = 3 ops: 54 + 2 = 56, 56 + 8 = 64, 64 - 64 = 0. That's 3 ops.

Constraints:

  • 0 <= n <= 10^9 (fits in 32-bit unsigned).

Difficulty: Medium Round: OA


Pattern Recognition ​

  • What is the input structure? A single integer.
  • What are we optimizing? Minimum operations, where each operation is ±2^k.
  • What pattern does this fit? Bit manipulation + greedy. Walk the binary representation from LSB to MSB and decide at each 1-bit whether to add or subtract.
  • Why does this pattern fit? Adding/subtracting 2^k toggles the k-th bit (and possibly ripples a carry). The minimum number of operations equals the minimum number of bit-toggles needed to reach zero, which is a local decision at each bit.

Approach ​

Brute Force — BFS on Integer States ​

Each state is an integer. From state x, you can reach x + 2^k or x - 2^k for any valid k. BFS from n until you hit 0.

Time: Exponential in the worst case, and state space unbounded (upward). Space: Same. Why insufficient: Intractable for n up to 10^9.

Optimal — Greedy on Binary Representation ​

Key Insight: Look at the lowest set bit. If it is an isolated 1 (...01), it is cheapest to subtract 1 (one op). If it is part of a run of 1s (...11), it is cheaper to add 1 and let the carry collapse the run upward.

Step-by-step (walk from LSB to MSB):

  1. If n is even, shift right (free — bit was 0, nothing to do).
  2. Else (LSB is 1):
    • If n == 1 or the next bit is 0 (...01 pattern), subtract 1 (op++).
    • Else (next bit is 1, meaning ...11 run), add 1 (op++), which carries up and may collapse multiple 1s into a single higher 1.
  3. Repeat until n == 0.

Why it works:

  • For an isolated 1, adding 1 would produce ...10, then you still need to deal with that higher 1 later — net cost >= 1 op for this bit plus downstream work. Subtracting 1 is better.
  • For a run of 1s (...0111), adding 1 makes it ...1000 — one op collapses the whole run into a single higher bit.

Time: O(log n) — one pass over the bits. Space: O(1).


Walkthrough ​

Trace on n = 39 (binary 100111):

stepn (binary)n (dec)LSBnext bitactionops
01001113911run → n + 1 = 401
1101000400—shift right1
210100200—shift right1
31010100—shift right1
4101510isolated → n - 1 = 42
510040—shift right2
61020—shift right2
71110isolated → n - 1 = 03

Answer: 3.


Implementation ​

typescript
function minOperationsToZero(n: number): number {
    let ops = 0;
    while (n > 0) {
        if ((n & 1) === 0) {
            // Even: shift right (free — bit was 0).
            n >>>= 1;
        } else if (n === 1 || (n & 2) === 0) {
            // Isolated 1 (pattern ...01): subtract 1.
            n -= 1;
            ops++;
        } else {
            // Run of 1s (pattern ...11): add 1 to carry-collapse.
            n += 1;
            ops++;
        }
    }
    return ops;
}
cpp
int minOperationsToZero(long long n) {
    int ops = 0;
    while (n > 0) {
        if ((n & 1) == 0) {
            // Even: shift right.
            n >>= 1;
        } else if (n == 1 || (n & 2) == 0) {
            // Isolated 1: subtract 1.
            n -= 1;
            ops++;
        } else {
            // Run of 1s: add 1 (carry).
            n += 1;
            ops++;
        }
    }
    return ops;
}

Watch out:

  1. Greedy rule is subtle. Add when you see ...11, subtract when you see ...01. Reversing this doubles the op count on runs.
  2. n == 1 special case. There is no "next bit" above bit 0; always subtract 1 here.
  3. Using signed right shift in TypeScript (>>) instead of unsigned (>>>) — fine here because n >= 0, but habit-forming bugs appear in related problems.

Complexity Analysis ​

TimeSpace
BFSExponentialExponential
Optimal (Bit Greedy)O(log n)O(1)

Bottleneck: The number of bits in n. For n <= 10^9, this is at most 30 iterations — essentially free.


Edge Cases ​

  1. n = 0 — return 0. Loop never runs.
  2. n is a power of 2 — one op (subtract n itself). The greedy shifts down to 1, then subtracts.
  3. n has all bits set up to some k (like 7 = 111) — add 1 once to get 1000, then shift down. 2 ops total.
  4. Alternating bits (like 21 = 10101) — three isolated 1s, three ops.
  5. Very large n near 2^30 — still O(30) steps. No overflow risk since adding 1 stays within 32-bit unsigned for n < 2^31.

  • LC 397 — Integer Replacement — Given n, either divide by 2 (if even) or add/subtract 1. Same greedy shape, same "look at next bit" rule.
  • LC 191 — Number of 1 Bits — Popcount. The lower bound on ops here is popcount(n), but runs allow you to do better.
  • LC 338 — Counting Bits — DP on bits. Same thinking patterns.

OA Strategy Notes ​

This is a mid-difficulty OA problem. Expect 15-25 minutes. The trap is convincing yourself of the greedy rule — when in doubt, test on small cases like n=3 (11), n=7 (111), n=11 (1011) to verify your rule before coding the full solution. With 75 minutes total for two problems, this one is usually the "tricky" one where your first instinct (popcount) is wrong.


What is Expected at Each Level ​

Junior: Likely struggles. Might propose popcount(n) as the answer, which is wrong for runs (e.g., 111 = 3 popcount but 2 ops). Needs the hint about runs.

Mid-level: Figures out the run-collapse insight with some thought. Writes the greedy loop correctly. Tests on n = 3, 7, 15 to verify.

Senior: Derives the rule rigorously: "The minimum ops equals the number of runs-of-1s plus the number of isolated 1s" or equivalently uses the formula popcount(n XOR (n >> 1)) framing. Discusses the connection to Integer Replacement (LC 397).

Frontend interview preparation reference.