1017. Convert to Base -2
Problem Description
Given an integer n
, you need to convert it to base -2 (negative two) and return the result as a binary string.
In base -2, instead of using powers of 2 (like in regular binary), we use powers of -2. The place values from right to left are:
- Position 0:
(-2)^0 = 1
- Position 1:
(-2)^1 = -2
- Position 2:
(-2)^2 = 4
- Position 3:
(-2)^3 = -8
- Position 4:
(-2)^4 = 16
- And so on...
For example:
- The number
2
in base -2 is"110"
because:1×4 + 1×(-2) + 0×1 = 4 - 2 + 0 = 2
- The number
3
in base -2 is"111"
because:1×4 + 1×(-2) + 1×1 = 4 - 2 + 1 = 3
- The number
4
in base -2 is"100"
because:1×4 + 0×(-2) + 0×1 = 4
The algorithm works by repeatedly checking if the current number is odd or even:
- If odd, we place a
'1'
at the current position and adjust the number by subtracting the current power of -2 - If even, we place a
'0'
at the current position - Then we divide by 2 and flip the sign of the power (multiply
k
by -1)
The resulting digits are collected and reversed to get the final answer. If the input is 0
, the function returns "0"
.
The key insight is that we're building the representation digit by digit, handling the alternating positive and negative place values by tracking the current power's sign with variable k
.
Intuition
To understand how to convert to base -2, let's first recall how we convert to regular base 2. In base 2, we repeatedly divide by 2 and take remainders. But base -2 is trickier because of the alternating signs.
The key observation is that any number can be expressed as a sum of powers of -2:
n = a₀×(-2)⁰ + a₁×(-2)¹ + a₂×(-2)² + a₃×(-2)³ + ...
where each aᵢ
is either 0 or 1.
Let's think about what happens when we look at n
modulo 2:
- If
n
is odd, thena₀
must be 1 (since all other terms are even) - If
n
is even, thena₀
must be 0
Once we determine a₀
, we need to find the remaining digits. If a₀ = 1
, we subtract 1 from n
(which is the value of (-2)⁰
). Now we have:
n - a₀ = a₁×(-2)¹ + a₂×(-2)² + a₃×(-2)³ + ...
To find a₁
, we can factor out (-2)
:
(n - a₀) = (-2) × (a₁×(-2)⁰ + a₂×(-2)¹ + a₃×(-2)² + ...)
This means: (n - a₀) / (-2) = -a₁ + a₂×(-2)¹ - a₃×(-2)² + ...
But wait, dividing by -2 is the same as dividing by 2 and then negating. However, we want to keep working with positive numbers for simplicity. The clever trick is to track the sign separately using a variable k
that alternates between 1 and -1.
When k = 1
(positive position), we subtract k
from n
if the bit is 1.
When k = -1
(negative position), we subtract k
from n
if the bit is 1 (which actually adds 1 to n
).
After determining each bit, we divide by 2 (not -2) and flip the sign of k
. This effectively simulates the base -2 conversion while keeping the arithmetic simple.
The process continues until n
becomes 0, building up the digits from least significant to most significant, which is why we reverse the result at the end.
Learn more about Math patterns.
Solution Approach
The implementation uses a straightforward iterative approach to build the base -2 representation digit by digit:
-
Initialize variables:
k = 1
: Tracks the sign of the current power of -2. Starts at 1 for(-2)⁰ = 1
ans = []
: List to collect the binary digits
-
Main conversion loop (
while n:
):- Check if current bit should be 1:
if n % 2:
- If
n
is odd, we need a '1' at this position - Append '1' to
ans
- Subtract the current power value:
n -= k
- When
k = 1
, this subtracts 1 (for positive powers) - When
k = -1
, this adds 1 (for negative powers)
- When
- If
- Otherwise, current bit is 0:
- Append '0' to
ans
- Append '0' to
- Check if current bit should be 1:
-
Prepare for next position:
- Divide
n
by 2:n //= 2
- Flip the sign for the next power:
k *= -1
- This alternates between positive and negative powers as we move to higher positions
- Divide
-
Build final result:
- Reverse the collected digits:
ans[::-1]
(since we built from least to most significant) - Join into a string:
''.join(ans[::-1])
- Handle edge case: Return
'0'
if the result is empty (when input was 0)
- Reverse the collected digits:
Example walkthrough for n = 6
:
- Initially:
n = 6
,k = 1
,ans = []
- Iteration 1:
6 % 2 = 0
→ append '0',n = 6 // 2 = 3
,k = -1
- Iteration 2:
3 % 2 = 1
→ append '1',n = (3 - (-1)) // 2 = 4 // 2 = 2
,k = 1
- Iteration 3:
2 % 2 = 0
→ append '0',n = 2 // 2 = 1
,k = -1
- Iteration 4:
1 % 2 = 1
→ append '1',n = (1 - (-1)) // 2 = 2 // 2 = 1
,k = 1
- Iteration 5:
1 % 2 = 1
→ append '1',n = (1 - 1) // 2 = 0
, loop ends - Result:
ans = ['0', '1', '0', '1', '1']
→ reversed →"11010"
Verification: 1×16 + 1×(-8) + 0×4 + 1×(-2) + 0×1 = 16 - 8 + 0 - 2 + 0 = 6
✓
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 walk through converting n = 3
to base -2:
Initial state: n = 3
, k = 1
(sign tracker), ans = []
(digit collector)
Iteration 1: Position 0, power = (-2)⁰ = 1
- Check:
3 % 2 = 1
(odd) → need a '1' at this position - Append '1' to ans:
ans = ['1']
- Adjust n:
n = 3 - k = 3 - 1 = 2
- Prepare for next:
n = 2 // 2 = 1
,k = 1 × (-1) = -1
Iteration 2: Position 1, power = (-2)¹ = -2
- Check:
1 % 2 = 1
(odd) → need a '1' at this position - Append '1' to ans:
ans = ['1', '1']
- Adjust n:
n = 1 - k = 1 - (-1) = 2
(subtracting -1 adds 1) - Prepare for next:
n = 2 // 2 = 1
,k = -1 × (-1) = 1
Iteration 3: Position 2, power = (-2)² = 4
- Check:
1 % 2 = 1
(odd) → need a '1' at this position - Append '1' to ans:
ans = ['1', '1', '1']
- Adjust n:
n = 1 - k = 1 - 1 = 0
- Loop ends since n = 0
Final result:
- Reverse ans:
['1', '1', '1']
→"111"
- Verification:
1×4 + 1×(-2) + 1×1 = 4 - 2 + 1 = 3
✓
The algorithm cleverly handles the alternating signs by tracking k
, which flips between 1 and -1. When we "subtract k" at a negative power position (k = -1), we're actually adding to n, which correctly accounts for the negative contribution of that bit.
Solution Implementation
1class Solution:
2 def baseNeg2(self, n: int) -> str:
3 """
4 Convert a non-negative integer to its base -2 representation.
5
6 Args:
7 n: A non-negative integer to convert
8
9 Returns:
10 String representation of the number in base -2
11 """
12 # Track the current power coefficient (alternates between 1 and -1)
13 power_coefficient = 1
14
15 # Store binary digits of the result (in reverse order initially)
16 result_digits = []
17
18 # Process the number until it becomes 0
19 while n > 0:
20 # Check if current bit position should be 1
21 if n % 2 == 1:
22 result_digits.append('1')
23 # Subtract the value contributed by this position
24 # (could be positive or negative based on power_coefficient)
25 n -= power_coefficient
26 else:
27 result_digits.append('0')
28
29 # Move to the next bit position
30 n //= 2
31
32 # Alternate the sign for the next power of -2
33 power_coefficient *= -1
34
35 # Reverse the digits and join them, or return '0' for input 0
36 return ''.join(reversed(result_digits)) if result_digits else '0'
37
1class Solution {
2 public String baseNeg2(int n) {
3 // Special case: if n is 0, return "0"
4 if (n == 0) {
5 return "0";
6 }
7
8 // Initialize sign multiplier (alternates between 1 and -1)
9 int signMultiplier = 1;
10
11 // StringBuilder to construct the result string
12 StringBuilder result = new StringBuilder();
13
14 // Convert to base -2 representation
15 while (n != 0) {
16 // Check if current bit position should be 1
17 if (n % 2 != 0) {
18 // Append 1 to the result
19 result.append(1);
20 // Adjust n by subtracting the value of current position
21 n -= signMultiplier;
22 } else {
23 // Append 0 to the result
24 result.append(0);
25 }
26
27 // Alternate the sign for next position (powers of -2)
28 signMultiplier *= -1;
29
30 // Move to the next bit position
31 n /= 2;
32 }
33
34 // Reverse the string since we built it from least significant bit
35 return result.reverse().toString();
36 }
37}
38
1class Solution {
2public:
3 string baseNeg2(int n) {
4 // Special case: if n is 0, return "0"
5 if (n == 0) {
6 return "0";
7 }
8
9 // sign_multiplier tracks the sign of the current position value
10 // In base -2: position 0 has value 1, position 1 has value -2,
11 // position 2 has value 4, position 3 has value -8, etc.
12 int sign_multiplier = 1;
13 string result;
14
15 // Convert number to base -2 representation
16 while (n != 0) {
17 // Check if current bit should be 1
18 if (n % 2 == 1) {
19 result.push_back('1');
20 // Subtract the value of current position from n
21 // This handles the alternating signs in base -2
22 n -= sign_multiplier;
23 } else {
24 result.push_back('0');
25 }
26
27 // Flip sign for next position (alternates between 1 and -1)
28 sign_multiplier *= -1;
29
30 // Move to next bit position
31 n /= 2;
32 }
33
34 // Result was built from least significant to most significant bit
35 // Reverse to get correct order
36 reverse(result.begin(), result.end());
37
38 return result;
39 }
40};
41
1/**
2 * Converts a decimal number to its base -2 representation
3 * @param n - The decimal number to convert
4 * @returns The base -2 representation as a string
5 */
6function baseNeg2(n: number): string {
7 // Handle the special case of zero
8 if (n === 0) {
9 return '0';
10 }
11
12 // Initialize the sign multiplier for alternating between positive and negative powers
13 let signMultiplier: number = 1;
14
15 // Array to store the binary digits of the result
16 const resultDigits: string[] = [];
17
18 // Process the number until it becomes zero
19 while (n !== 0) {
20 // Check if the current bit position should be 1
21 if (n % 2 !== 0) {
22 resultDigits.push('1');
23 // Adjust n by subtracting the current power of -2
24 n -= signMultiplier;
25 } else {
26 resultDigits.push('0');
27 }
28
29 // Alternate the sign for the next power of -2
30 signMultiplier *= -1;
31
32 // Integer division by 2 to process the next bit
33 n = Math.floor(n / 2);
34 }
35
36 // Reverse the digits to get the correct order (most significant bit first)
37 return resultDigits.reverse().join('');
38}
39
Time and Space Complexity
Time Complexity: O(log n)
The algorithm processes the number n
by repeatedly dividing it by 2 (through n //= 2
) until n
becomes 0. This creates a loop that runs approximately log₂(n)
times. In each iteration, we perform constant-time operations:
- Checking if
n % 2
is true:O(1)
- Appending to the list:
O(1)
amortized - Arithmetic operations (
n -= k
,n //= 2
,k *= -1
):O(1)
After the loop, we reverse the list and join it, which takes O(log n)
time since the list has at most O(log n)
elements.
Therefore, the overall time complexity is O(log n) + O(log n) = O(log n)
.
Space Complexity: O(log n)
The space is used for:
- The
ans
list which stores the binary digits. In the worst case, this list will have approximatelylog₂(n)
elements since we're essentially converting the number to a base representation. - The reversed list created during
ans[::-1]
also takesO(log n)
space. - Other variables (
k
,n
) useO(1)
space.
The total space complexity is O(log n)
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Handling of Negative Adjustments
One of the most common mistakes is misunderstanding how the adjustment n -= k
works when dealing with negative powers. When k = -1
(representing a negative power position), subtracting k
actually adds 1 to n
. This counterintuitive behavior often leads to errors.
Incorrect approach:
if n % 2 == 1: result_digits.append('1') n -= 1 # Wrong! Always subtracting 1 ignores the sign
Correct approach:
if n % 2 == 1: result_digits.append('1') n -= power_coefficient # Correctly handles both positive and negative powers
2. Forgetting to Handle the Zero Case
The algorithm naturally produces an empty list when n = 0
, but forgetting to handle this edge case results in returning an empty string instead of "0"
.
Pitfall:
# Missing edge case handling
return ''.join(reversed(result_digits)) # Returns "" for n=0
Solution:
return ''.join(reversed(result_digits)) if result_digits else '0'
3. Building the Result in Wrong Order
Since we process bits from least significant to most significant, the digits are collected in reverse order. Forgetting to reverse them produces an incorrect result.
Wrong:
return ''.join(result_digits) # Digits are in reverse order!
Correct:
return ''.join(reversed(result_digits))
4. Integer Division Confusion in Python 2 vs Python 3
In Python 2, /
performs integer division for integers, while in Python 3, //
is required for integer division. Using /
in Python 3 creates float values that break the algorithm.
Problematic in Python 3:
n = n / 2 # Creates a float, causing issues in subsequent iterations
Correct for both Python 2 and 3:
n //= 2 # Integer division works consistently
5. Misunderstanding the Alternating Pattern
Some might try to track the actual power value (1, -2, 4, -8, ...) instead of just the sign coefficient, leading to unnecessary complexity and potential overflow issues with large numbers.
Overcomplicated:
power = 1 while n > 0: if n % 2 == 1: n -= power power *= -2 # Tracking actual power values
Simplified and correct:
k = 1 # Just track the sign while n > 0: if n % 2 == 1: n -= k k *= -1 # Simply alternate the sign
How many ways can you arrange the three letters A, B and C?
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!