Given the binary representation of an integer as a string s
, return the number of steps to reduce it to 1
under the following rules:
2
.1
to it.It is guaranteed that you can always reach one for all test cases.
For example:
s = "1101"
should return 6
because "1101" corresponds to number 13 in their decimal representation. The steps are: 1) 13 is odd, add 1 and obtain 14. 2) 14 is even, divide by 2 and obtain 7. 3) 7 is odd, add 1 and obtain 8. 4) 8 is even, divide by 2 and obtain 4. 5) 4 is even, divide by 2 and obtain 2. 6) 2 is even, divide by 2 and obtain 1.s = "10"
should return 1
because "10" corresponds to number 2 in their decimal representation. The step is: 1) 2 is even, divide by 2 and obtain 1.s = "1"
should return 0
.Can you implement an efficient solution for this problem?
A straightforward approach is to simulate the process as described in the problem statement. We can convert the binary string to an integer, then repeatedly apply the rules until we reach 1, counting the steps.
def num_steps_naive(s: str) -> int:
num = int(s, 2)
steps = 0
while num > 1:
if num % 2 == 0:
num //= 2
else:
num += 1
steps += 1
return steps
In the worst case, 's' represents a number close to 2^500. Each step either divides the number by 2 or adds 1. The number of steps is proportional to the value of the number.
We use a constant amount of extra space.
We can solve this problem without explicitly converting the binary string to an integer. Instead, we can directly operate on the binary string. We iterate from right to left. If we encounter a '0', we divide by 2 (equivalent to a right shift, so incrementing steps). If we encounter a '1', we add 1 (which may cause carries). The key is to track the carry.
steps = 0
and carry = 0
.s
from right to left (excluding the leftmost bit).carry
is 0, increment steps
by 1.carry
is 1, increment steps
by 2 (1 for flipping 0 to 1, and 1 for the next carry).carry
is 0, increment steps
by 2 (1 for flipping 1 to 0, and 1 for the next carry).carry
is 1, increment steps
by 1 (1 for flipping 1 to 0; carry remains 1).steps
to account for the final carry propagation to the leftmost bit.def num_steps(s: str) -> int:
steps = 0
carry = 0
for i in range(len(s) - 1, 0, -1):
if s[i] == '0':
if carry == 0:
steps += 1
else:
steps += 2
else:
if carry == 0:
steps += 2
carry = 1
else:
steps += 1
steps += carry # Account for the final carry propagation
return steps
We iterate through the binary string once.
We use a constant amount of extra space for the steps
and carry
variables.