Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1404. Number of Steps to Reduce a Number in Binary Representation to One - Leetcode Solution

Problem Description

Given a binary string s representing a positive integer, your task is to determine the number of steps required to reduce the value to 1 using the following operations:

  • If the current number is even, divide it by 2 (i.e., remove the last bit).
  • If the current number is odd and greater than 1, add 1 to it.

Repeat this process until the number becomes 1. Return the total number of steps taken.

Constraints:

  • 1 <= s.length <= 500
  • s consists only of characters '0' or '1'
  • s does not contain leading zeros (except for "1" itself)

Thought Process

At first glance, the problem seems to require simulating arithmetic operations on a binary number. The brute-force approach would be to convert the binary string to an integer, then repeatedly apply the two rules until the number is reduced to 1, counting the steps.

However, the number can be very large (up to 500 bits), so direct integer conversion may not be efficient or even feasible in some languages. Instead, we can process the binary string directly, mimicking the operations as if we were doing manual binary arithmetic.

The key insight is that dividing by 2 in binary is just removing the last bit (right shift), and adding 1 requires handling carries, similar to how addition works in binary.

Solution Approach

To efficiently solve the problem, we process the binary string from the end (least significant bit) to the start (most significant bit). Here's how we approach it:

  1. Initialize a step counter (steps) to 0. Also, use a carry variable to track if a previous addition has affected the current bit.
  2. Start from the rightmost bit (the least significant bit) and iterate towards the left, stopping at the first bit (since we want to reduce to 1).
  3. For each bit:
    • If the (current bit + carry) is 0 (even), we can "divide by 2" (i.e., move left), so increment steps by 1.
    • If the sum is 1 (odd), we need to "add 1" (which may cause a carry), so increment steps by 2 (one for addition, one for division), and set carry = 1.
  4. Continue until you reach the most significant bit (the leftmost '1').
  5. Return the step counter.

This approach avoids converting the whole binary string to an integer, and works efficiently even for very long strings.

Example Walkthrough

Let's walk through the process with an example:

Input: s = "1101" (which is 13 in decimal)

  • Start: 1101 (odd) → add 1 → 1110 (step 1), divide by 2 → 111 (step 2)
  • 111 (odd) → add 1 → 1000 (step 3), divide by 2 → 100 (step 4)
  • 100 (even) → divide by 2 → 10 (step 5)
  • 10 (even) → divide by 2 → 1 (step 6)

Total steps: 6

Each step follows the rules: add 1 if odd, divide by 2 if even, until 1 is reached.

Time and Space Complexity

Brute-force approach: If we convert the binary string to an integer and simulate the process, each operation could be O(N) for very large numbers due to the cost of big integer arithmetic, leading to O(N2) time in the worst case.

Optimized approach: By processing the string directly, we only need to scan through the string once, making the time complexity O(N), where N is the length of the string. Space complexity is O(1), as we only use a few variables (step counter, carry), not any additional data structures proportional to input size.

Summary

The problem is efficiently solved by simulating binary operations directly on the string, avoiding costly conversions or big integer arithmetic. The key insight is that dividing by 2 is a right shift in binary, and adding 1 may introduce a carry. By scanning from the least significant bit to the most significant, we count the required steps to reduce the binary number to 1. This approach is both elegant and efficient, with linear time and constant space complexity.

Code Implementation

class Solution:
    def numSteps(self, s: str) -> int:
        steps = 0
        carry = 0
        n = len(s)
        for i in range(n - 1, 0, -1):
            bit = int(s[i])
            if bit + carry == 1:
                # odd, add 1 and then divide by 2
                steps += 2
                carry = 1
            else:
                # even, just divide by 2
                steps += 1
        # If there's a carry at the end, we need one more step
        if carry:
            steps += 1
        return steps
      
class Solution {
public:
    int numSteps(string s) {
        int steps = 0, carry = 0;
        int n = s.size();
        for (int i = n - 1; i > 0; --i) {
            int bit = s[i] - '0';
            if (bit + carry == 1) {
                steps += 2;
                carry = 1;
            } else {
                steps += 1;
            }
        }
        if (carry) steps += 1;
        return steps;
    }
};
      
class Solution {
    public int numSteps(String s) {
        int steps = 0, carry = 0;
        int n = s.length();
        for (int i = n - 1; i > 0; --i) {
            int bit = s.charAt(i) - '0';
            if (bit + carry == 1) {
                steps += 2;
                carry = 1;
            } else {
                steps += 1;
            }
        }
        if (carry == 1) steps += 1;
        return steps;
    }
}
      
var numSteps = function(s) {
    let steps = 0, carry = 0;
    let n = s.length;
    for (let i = n - 1; i > 0; --i) {
        let bit = parseInt(s[i]);
        if (bit + carry === 1) {
            steps += 2;
            carry = 1;
        } else {
            steps += 1;
        }
    }
    if (carry === 1) steps += 1;
    return steps;
};