Taro Logo

Minimum Operations to Reduce an Integer to 0

Medium
Google logo
Google
1 view
Topics:
Bit ManipulationGreedy Algorithms

You are given a positive integer n, you can do the following operation any number of times:

  • Add or subtract a power of 2 from n.

Return the minimum number of operations to make n equal to 0.

A number x is power of 2 if x == 2<sup>i</sup> where i >= 0.

Example 1:

Input: n = 39 Output: 3 Explanation: We can do the following operations:

  • Add 20 = 1 to n, so now n = 40.
  • Subtract 23 = 8 from n, so now n = 32.
  • Subtract 25 = 32 from n, so now n = 0. It can be shown that 3 is the minimum number of operations we need to make n equal to 0.

Example 2:

Input: n = 54 Output: 3 Explanation: We can do the following operations:

  • Add 21 = 2 to n, so now n = 56.
  • Add 23 = 8 to n, so now n = 64.
  • Subtract 26 = 64 from n, so now n = 0. So the minimum number of operations is 3.

How would you solve this problem efficiently?

Solution


Naive Approach

A brute-force approach would involve trying all possible combinations of adding or subtracting powers of 2 until we reach 0. However, this is highly inefficient and impractical due to the exponential nature of possible combinations.

Optimal Approach

The key idea behind the optimal solution is to observe the binary representation of the number n. We want to minimize the number of operations to reach 0 by either adding or subtracting powers of 2. At each step, we consider adding or subtracting the nearest power of 2. A more efficient approach involves analyzing the binary representation of 'n'. We can traverse the bits from right to left. If we encounter a '0', we move to the next bit. If we encounter a '1', we have two choices: either subtract 2^i or add 2^i.

Let's consider an example: n = 39 (binary: 100111).

  1. Start from the rightmost bit (LSB).
  2. If the bit is '1', we have two choices: add or subtract a power of 2.
  3. If the bit is '0', no operation is needed for this bit.

For 39 (100111):

  • LSB is 1. We can either subtract 2^0 or add 2^0.
  • Next bit is 1. We can either subtract or add 2^1.
  • Next bit is 1. We can either subtract or add 2^2.

We try to group consecutive 1s. If there are many consecutive 1s, it might be beneficial to add a power of 2 to convert them to a single 1 with some 0s in between.

For example:

  • 111 can be converted to 1000 with a single addition (requires 1 operation).
  • 11 can be converted to 100 with a single addition (requires 1 operation).

Here's the algorithm:

  1. Initialize operations = 0.
  2. While n > 0:
    • If n is even, n = n / 2.
    • If n is odd:
      • Choose the operation (add or subtract) that results in fewer operations later.
      • If n == 1, operations++, n = 0.
      • Otherwise, compare n + 1 and n - 1 after dividing by 2. If (n + 1) / 2 has fewer consecutive 1s or is smaller, increment n and operations. Otherwise, decrement n and increment operations.

Code

def min_operations(n):
    operations = 0
    while n > 0:
        if n % 2 == 0:
            n //= 2
        else:
            if n == 1:
                operations += 1
                n = 0
            elif (n == 3) : # Special case for n == 3
                 operations += 2
                 n = 0
            elif (n + 1) % 4 == 0:
                n += 1
                operations += 1
            else:
                n -= 1
                operations += 1
    return operations

# Example usage
n = 39
print(min_operations(n))  # Output: 3

n = 54
print(min_operations(n)) # Output: 3

Explanation of the Code:

The min_operations function takes an integer n as input and returns the minimum number of operations to make n equal to 0. The while loop continues until n becomes 0. If n is even, we simply divide it by 2. If n is odd, we check if n is 1 (base case). If not, we check if adding 1 to n makes it divisible by 4. If it does, we increment n; otherwise, we decrement n. In both cases, we increment the operations counter.

Edge Cases

  • n = 1: Requires 1 operation (subtract 2^0).
  • n = 2: Requires 1 operation (subtract 2^1).
  • n = 3: Requires 2 operations (add 2^0 to get 4, then subtract 2^2).

Time Complexity

The time complexity is O(log n) because, in each step, we are either dividing n by 2 or incrementing/decrementing it, effectively reducing the magnitude of n logarithmically.

Space Complexity

The space complexity is O(1) because we are using only a constant amount of extra space, regardless of the input size.