1342. Number of Steps to Reduce a Number to Zero
Problem Description
You are given a positive integer num
. Your task is to count how many steps it takes to reduce this number to zero by following these rules:
- If the current number is even, divide it by 2
- If the current number is odd, subtract 1 from it
Each operation (division by 2 or subtraction of 1) counts as one step. Continue applying these operations until the number becomes 0, then return the total number of steps taken.
For example, if num = 14
:
- Step 1: 14 is even, divide by 2 to get 7
- Step 2: 7 is odd, subtract 1 to get 6
- Step 3: 6 is even, divide by 2 to get 3
- Step 4: 3 is odd, subtract 1 to get 2
- Step 5: 2 is even, divide by 2 to get 1
- Step 6: 1 is odd, subtract 1 to get 0
The answer would be 6 steps.
The solution uses a while loop that continues until num
becomes 0. In each iteration, it checks if the number is odd using the bitwise AND operation num & 1
(which returns 1 if the last bit is 1, indicating an odd number). If odd, it subtracts 1; if even, it performs a right shift num >>= 1
which is equivalent to dividing by 2. A counter ans
tracks the total number of steps.
Intuition
The problem asks us to repeatedly apply two operations based on whether the number is even or odd. This naturally suggests a simulation approach where we simply follow the given rules until we reach zero.
The key insight is that we need to keep track of two things: the current value of the number and the count of operations performed. Since we don't know in advance how many steps it will take, a while loop that continues until num
becomes 0 is the natural choice.
For checking whether a number is even or odd, we have multiple options. The traditional approach would be to use the modulo operator num % 2
. However, we can optimize this using bitwise operations. When we look at the binary representation of any number, the least significant bit (rightmost bit) determines if it's odd or even - if this bit is 1, the number is odd; if it's 0, the number is even. We can check this using num & 1
, which performs a bitwise AND with 1 and returns 1 for odd numbers and 0 for even numbers.
Similarly, for dividing by 2, instead of using regular division num // 2
, we can use the right shift operator num >> 1
. Shifting bits to the right by one position is equivalent to integer division by 2, but it's a more efficient operation at the hardware level.
The algorithm is straightforward: keep a counter starting at 0, and in each iteration, check if the number is odd or even, perform the appropriate operation, increment the counter, and continue until the number reaches 0. The counter at the end gives us the total number of steps required.
Learn more about Math patterns.
Solution Approach
The implementation follows a straightforward simulation approach using a while loop. Let's walk through the algorithm step by step:
-
Initialize a counter: Start with
ans = 0
to keep track of the number of steps taken. -
Loop until zero: Use
while num:
which continues as long asnum
is not zero. In Python, any non-zero integer evaluates toTrue
, so the loop runs untilnum
becomes 0. -
Check odd or even: Inside the loop, use the bitwise AND operation
num & 1
to determine if the number is odd:num & 1
returns 1 if the least significant bit is 1 (odd number)num & 1
returns 0 if the least significant bit is 0 (even number)
-
Perform the appropriate operation:
- If
num & 1
is true (odd): Subtract 1 from the number usingnum -= 1
- If
num & 1
is false (even): Divide by 2 using the right shift operatornum >>= 1
- If
-
Increment the counter: After each operation, increment
ans += 1
to count this step. -
Return the result: Once the loop exits (when
num
becomes 0), returnans
which contains the total number of steps.
The bitwise operations used here are optimizations:
num & 1
is more efficient thannum % 2
for checking odd/evennum >> 1
is more efficient thannum // 2
for division by 2
The time complexity is O(log n)
because in the worst case (when we have the maximum number of divisions by 2), we're essentially counting the number of bits in the binary representation of the number. The space complexity is O(1)
as we only use a constant amount of extra space for the counter variable.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's trace through the algorithm with num = 11
:
Initial State: num = 11
, ans = 0
Step 1:
- Check:
11 & 1 = 1
(odd, because binary 1011 ends in 1) - Operation:
num = 11 - 1 = 10
- Update counter:
ans = 1
Step 2:
- Check:
10 & 1 = 0
(even, because binary 1010 ends in 0) - Operation:
num = 10 >> 1 = 5
(shift 1010 right to get 0101) - Update counter:
ans = 2
Step 3:
- Check:
5 & 1 = 1
(odd, because binary 0101 ends in 1) - Operation:
num = 5 - 1 = 4
- Update counter:
ans = 3
Step 4:
- Check:
4 & 1 = 0
(even, because binary 0100 ends in 0) - Operation:
num = 4 >> 1 = 2
(shift 0100 right to get 0010) - Update counter:
ans = 4
Step 5:
- Check:
2 & 1 = 0
(even, because binary 0010 ends in 0) - Operation:
num = 2 >> 1 = 1
(shift 0010 right to get 0001) - Update counter:
ans = 5
Step 6:
- Check:
1 & 1 = 1
(odd, because binary 0001 ends in 1) - Operation:
num = 1 - 1 = 0
- Update counter:
ans = 6
Loop exits because num = 0
Return: ans = 6
The sequence of operations was: 11 → 10 → 5 → 4 → 2 → 1 → 0, taking 6 steps total.
Solution Implementation
1class Solution:
2 def numberOfSteps(self, num: int) -> int:
3 """
4 Count the number of steps to reduce a number to zero.
5 For odd numbers: subtract 1
6 For even numbers: divide by 2
7
8 Args:
9 num: A non-negative integer to be reduced to zero
10
11 Returns:
12 The number of steps required to reduce num to zero
13 """
14 step_count = 0
15
16 # Continue until the number becomes zero
17 while num > 0:
18 # Check if the number is odd using bitwise AND
19 if num & 1: # Odd number (last bit is 1)
20 num -= 1
21 else: # Even number (last bit is 0)
22 num >>= 1 # Right shift by 1 (equivalent to dividing by 2)
23
24 # Increment the step counter
25 step_count += 1
26
27 return step_count
28
1class Solution {
2
3 /**
4 * Counts the number of steps to reduce a number to zero.
5 * In each step:
6 * - If the number is even, divide it by 2
7 * - If the number is odd, subtract 1 from it
8 *
9 * @param num The input number to be reduced to zero
10 * @return The number of steps required to reduce num to zero
11 */
12 public int numberOfSteps(int num) {
13 int stepCount = 0;
14
15 // Continue until the number becomes zero
16 while (num != 0) {
17 // Check if the number is odd using bitwise AND with 1
18 // If odd (last bit is 1), subtract 1; if even, divide by 2 using right shift
19 if ((num & 1) == 1) {
20 num = num - 1; // Odd number: subtract 1
21 } else {
22 num = num >> 1; // Even number: divide by 2 (right shift by 1)
23 }
24
25 // Increment the step counter
26 stepCount++;
27 }
28
29 return stepCount;
30 }
31}
32
1class Solution {
2public:
3 int numberOfSteps(int num) {
4 int stepCount = 0;
5
6 // Continue until num becomes 0
7 while (num) {
8 // Check if num is odd (last bit is 1) or even (last bit is 0)
9 // If odd: subtract 1; If even: divide by 2 (right shift by 1)
10 num = (num & 1) ? (num - 1) : (num >> 1);
11
12 // Increment the step counter
13 ++stepCount;
14 }
15
16 return stepCount;
17 }
18};
19
1/**
2 * Counts the number of steps to reduce a number to zero.
3 * In each step: if the number is even, divide it by 2; if odd, subtract 1.
4 *
5 * @param num - The input number to be reduced to zero
6 * @returns The number of steps required
7 */
8function numberOfSteps(num: number): number {
9 // Initialize step counter
10 let stepCount = 0;
11
12 // Continue until the number becomes zero
13 while (num > 0) {
14 // Check if the number is odd using bitwise AND
15 if (num & 1) {
16 // If odd, subtract 1
17 num = num - 1;
18 } else {
19 // If even, divide by 2 using unsigned right shift
20 num = num >>> 1;
21 }
22
23 // Increment the step counter
24 stepCount++;
25 }
26
27 // Return the total number of steps
28 return stepCount;
29}
30
Time and Space Complexity
Time Complexity: O(log n)
The algorithm processes the number num
by either subtracting 1 (if odd) or dividing by 2 (if even) until it reaches 0. The key insight is that each operation reduces the problem size:
- When
num
is odd, we subtract 1, making it even - When
num
is even, we right shift (divide by 2), which reduces the number of bits
In the worst case, for a number with k
bits, we need at most 2k - 1
operations (alternating between subtracting 1 and dividing by 2). Since a number n
has approximately log₂(n)
bits, the time complexity is O(log n)
.
Space Complexity: O(1)
The algorithm uses only a constant amount of extra space:
- Variable
ans
to count the steps - The input
num
is modified in place - No additional data structures are used
The space usage doesn't grow with the input size, making it constant space complexity.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Inefficient Condition Checking and Operations
A common pitfall is using less efficient operations for checking odd/even and performing division:
Problematic Code:
def numberOfSteps(self, num: int) -> int:
step_count = 0
while num > 0:
if num % 2 == 1: # Less efficient modulo operation
num = num - 1
else:
num = num / 2 # Using float division instead of integer division
step_count += 1
return step_count
Issues:
- Using
num % 2
instead ofnum & 1
for odd/even checking is slower - Using
/
creates a float, which can cause issues with large numbers and requires type conversion - Not using in-place operations misses optimization opportunities
Solution: Use bitwise operations and ensure integer division:
if num & 1: # Bitwise AND for odd check num -= 1 # In-place subtraction else: num >>= 1 # Bitwise right shift (integer division by 2)
2. Edge Case Handling for Zero
While the current solution handles zero correctly (returns 0 steps), developers might overthink and add unnecessary special case handling:
Overcomplicated Code:
def numberOfSteps(self, num: int) -> int:
if num == 0: # Unnecessary special case
return 0
step_count = 0
while num > 0:
# ... rest of the logic
Solution: The while loop naturally handles zero by not executing at all, returning 0 steps. No special case needed.
3. Alternative One-Line Implementation Pitfall
Some might try to optimize this into a mathematical formula but miss edge cases:
Problematic Approach:
def numberOfSteps(self, num: int) -> int:
if num == 0:
return 0
# Trying to use bit manipulation formula
return bin(num).count('1') + len(bin(num)) - 3
Issues:
- This formula counts the number of 1s in binary representation plus the bit length minus 3
- While mathematically correct for most cases, it's less readable and harder to understand
- The
-3
accounts for the '0b' prefix and adjustments, making it error-prone
Solution: Stick with the simulation approach for clarity and maintainability. The performance difference is negligible for reasonable input sizes.
What is the best way of checking if an element exists in an unsorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!