Given an integer num
, return the number of steps to reduce it to zero.
In one step, if the current number is even, you have to divide it by 2
, otherwise, you have to subtract 1
from it.
Example 1:
Input: num = 14 Output: 6 Explanation: Step 1) 14 is even; divide by 2 and obtain 7. Step 2) 7 is odd; subtract 1 and obtain 6. Step 3) 6 is even; divide by 2 and obtain 3. Step 4) 3 is odd; subtract 1 and obtain 2. Step 5) 2 is even; divide by 2 and obtain 1. Step 6) 1 is odd; subtract 1 and obtain 0.
Example 2:
Input: num = 8 Output: 4 Explanation: Step 1) 8 is even; divide by 2 and obtain 4. Step 2) 4 is even; divide by 2 and obtain 2. Step 3) 2 is even; divide by 2 and obtain 1. Step 4) 1 is odd; subtract 1 and obtain 0.
Example 3:
Input: num = 123 Output: 12
Constraints:
0 <= num <= 106
The problem asks to find the number of steps required to reduce a given integer num
to zero. In each step, if the number is even, we divide it by 2; otherwise, we subtract 1.
The most efficient approach is an iterative one, directly manipulating the number until it becomes zero. Recursive solutions are presented for completeness but are less efficient due to the overhead of function calls.
Algorithm:
steps
counter to 0.num
is not zero.num
is even (using the modulo operator %
or bitwise AND operator &
).num
by 2 (using right bit shift >>
is faster); otherwise, subtract 1.steps
counter in each iteration.num
becomes 0), return the value of steps
.Time and Space Complexity Analysis:
Time Complexity: The time complexity is O(log n), where n is the input number. This is because in the worst-case scenario (when the number is repeatedly divided by 2), the number of steps is proportional to the logarithm base 2 of the input number. The number of times we can halve a number before reaching 1 is logarithmic. The iterative solution has the advantage of a better constant factor than the recursive solution.
Space Complexity: The space complexity is O(1) for both iterative and recursive approaches (excluding the recursion stack for the recursive approach). The iterative method uses a constant amount of extra space, whereas the recursive solution uses space proportional to the recursion depth, which in the worst case is O(log n).
The code examples below illustrate the iterative approach (more efficient). Recursive solutions are provided for comparison, showcasing the same logic but with higher overhead.
Iterative Approach (Efficient):
Python:
class Solution:
def numberOfSteps(self, num: int) -> int:
steps = 0
while num > 0:
if num % 2 == 0:
num //= 2
else:
num -= 1
steps += 1
return steps
Java:
class Solution {
public int numberOfSteps(int num) {
int steps = 0;
while (num > 0) {
if (num % 2 == 0) {
num /= 2;
} else {
num--;
}
steps++;
}
return steps;
}
}
C++:
class Solution {
public:
int numberOfSteps(int num) {
int steps = 0;
while (num > 0) {
if (num % 2 == 0) {
num /= 2;
} else {
num--;
}
steps++;
}
return steps;
}
};
Go:
func numberOfSteps(num int) int {
steps := 0
for num > 0 {
if num%2 == 0 {
num /= 2
} else {
num--
}
steps++
}
return steps
}
JavaScript:
var numberOfSteps = function(num) {
let steps = 0;
while (num > 0) {
if (num % 2 === 0) {
num /= 2;
} else {
num--;
}
steps++;
}
return steps;
};
Recursive Approach (Less Efficient):
Python:
class Solution:
def numberOfSteps(self, num: int) -> int:
if num == 0:
return 0
return 1 + (self.numberOfSteps(num // 2) if num % 2 == 0 else self.numberOfSteps(num - 1))
The recursive versions follow the same logic but are generally less efficient due to function call overhead. The iterative approach is recommended for optimal performance.