1009. Complement of Base 10 Integer
Problem Description
The problem asks you to find the complement of a given integer. The complement is obtained by flipping all the bits in the binary representation of the number - changing all 0
s to 1
s and all 1
s to 0
s.
For example:
- The integer
5
has binary representation"101"
- After flipping all bits:
0
becomes1
,1
becomes0
,0
becomes1
- This gives us
"010"
, which equals the integer2
Given an integer n
, you need to return its complement.
The solution works by iterating through each bit of the input number n
. For each bit position i
:
- It extracts the current bit using
n & 1
- Flips it using XOR with
1
(which gives0
if the bit is1
, and1
if the bit is0
) - Places this flipped bit at the correct position in the answer using left shift
<< i
- Combines it with the existing answer using OR operation
|=
- Moves to the next bit by right shifting
n
by1
The special case where n = 0
is handled separately, returning 1
since the complement of 0
(all zeros) would be 1
(a single one).
Intuition
To find the complement of a number, we need to flip every bit in its binary representation. The key insight is that we can process the number bit by bit from right to left.
Think about how we normally read binary numbers - each bit position has a specific value (powers of 2). When building the complement, we want to preserve these positions but flip the actual bit values.
The natural approach is to:
- Look at each bit of the original number
- Flip it (if it's
1
make it0
, if it's0
make it1
) - Place this flipped bit in the same position in our result
To flip a bit, we can use XOR with 1
: bit ^ 1
. This works because:
0 ^ 1 = 1
(flips0
to1
)1 ^ 1 = 0
(flips1
to0
)
We build the answer incrementally by processing one bit at a time. We extract the rightmost bit using n & 1
, flip it, then position it correctly in our answer using left shift. After processing each bit, we right shift n
to move to the next bit.
The special case of n = 0
needs separate handling because our loop wouldn't execute (since 0
has no 1
bits to process), but we know the complement of 0
should be 1
.
This bit-by-bit construction ensures we only flip the bits that actually exist in the original number's representation, avoiding the issue of flipping leading zeros that aren't part of the number.
Solution Approach
The solution uses bit manipulation to construct the complement bit by bit.
First, we handle the edge case: if n
is 0
, we immediately return 1
since the complement of 0
is 1
.
For all other cases, we initialize two variables:
ans = 0
: This will store our final complement valuei = 0
: This tracks the current bit position we're processing
The main algorithm processes n
bit by bit using a while loop that continues as long as n
is not zero:
-
Extract and flip the current bit:
(n & 1 ^ 1)
n & 1
extracts the rightmost bit ofn
^ 1
flips this bit (XOR with 1 inverts the bit)
-
Position the flipped bit:
<< i
- Left shift the flipped bit by
i
positions to place it at the correct position in the result
- Left shift the flipped bit by
-
Add to the answer:
ans |= ...
- Use OR operation to set this bit in our answer
-
Move to the next bit:
- Increment
i
to track the next bit position - Right shift
n
by 1 (n >>= 1
) to process the next bit
- Increment
The loop naturally terminates when all bits of n
have been processed (when n
becomes 0
after all the right shifts).
For example, with n = 5
(binary 101
):
- Iteration 1: Process bit
1
, flip to0
, place at position 0 - Iteration 2: Process bit
0
, flip to1
, place at position 1 - Iteration 3: Process bit
1
, flip to0
, place at position 2 - Result:
010
which is2
in decimal
This approach ensures we only process the actual bits in the number's representation, avoiding issues with leading zeros.
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 n = 5
(binary: 101
).
Initial State:
n = 5
(binary:101
)ans = 0
(binary:000
)i = 0
Iteration 1:
- Current rightmost bit of
n
:n & 1 = 101 & 001 = 1
- Flip the bit:
1 ^ 1 = 0
- Position it:
0 << 0 = 0
- Update answer:
ans = 000 | 000 = 000
- Move to next bit:
n = 101 >> 1 = 010
(which is 2),i = 1
Iteration 2:
- Current rightmost bit of
n
:n & 1 = 010 & 001 = 0
- Flip the bit:
0 ^ 1 = 1
- Position it:
1 << 1 = 010
- Update answer:
ans = 000 | 010 = 010
- Move to next bit:
n = 010 >> 1 = 001
(which is 1),i = 2
Iteration 3:
- Current rightmost bit of
n
:n & 1 = 001 & 001 = 1
- Flip the bit:
1 ^ 1 = 0
- Position it:
0 << 2 = 000
- Update answer:
ans = 010 | 000 = 010
- Move to next bit:
n = 001 >> 1 = 000
(which is 0),i = 3
Loop Terminates (n = 0)
Final Result: ans = 010
(binary) = 2
(decimal)
We successfully flipped 101
to 010
, converting 5 to its complement 2.
Solution Implementation
1class Solution:
2 def bitwiseComplement(self, n: int) -> int:
3 # Special case: complement of 0 is 1
4 if n == 0:
5 return 1
6
7 # Initialize result and bit position counter
8 result = 0
9 bit_position = 0
10
11 # Process each bit of n from right to left
12 while n > 0:
13 # Get the rightmost bit, flip it (XOR with 1),
14 # shift it to the correct position, and add to result
15 flipped_bit = (n & 1) ^ 1
16 result |= flipped_bit << bit_position
17
18 # Move to the next bit position
19 bit_position += 1
20
21 # Right shift n to process the next bit
22 n >>= 1
23
24 return result
25
1class Solution {
2 public int bitwiseComplement(int n) {
3 // Special case: complement of 0 is 1
4 if (n == 0) {
5 return 1;
6 }
7
8 int result = 0;
9 int bitPosition = 0;
10
11 // Process each bit of n from right to left
12 while (n != 0) {
13 // Get the least significant bit of n and flip it (0->1, 1->0)
14 int flippedBit = (n & 1) ^ 1;
15
16 // Place the flipped bit at the correct position in result
17 result |= flippedBit << bitPosition;
18
19 // Move to the next bit position
20 bitPosition++;
21
22 // Right shift n to process the next bit
23 n >>= 1;
24 }
25
26 return result;
27 }
28}
29
1class Solution {
2public:
3 int bitwiseComplement(int n) {
4 // Special case: complement of 0 is 1
5 if (n == 0) {
6 return 1;
7 }
8
9 int result = 0;
10 int bitPosition = 0;
11
12 // Process each bit of n from right to left
13 while (n != 0) {
14 // Get the least significant bit, flip it (XOR with 1),
15 // shift it to the correct position, and add to result
16 int flippedBit = (n & 1) ^ 1;
17 result |= flippedBit << bitPosition;
18
19 // Move to the next bit position
20 bitPosition++;
21
22 // Right shift n to process the next bit
23 n >>= 1;
24 }
25
26 return result;
27 }
28};
29
1/**
2 * Finds the bitwise complement of a non-negative integer.
3 * The complement of a binary number is obtained by flipping all its bits.
4 * @param n - The non-negative integer to find the complement of
5 * @returns The bitwise complement of n
6 */
7function bitwiseComplement(n: number): number {
8 // Special case: complement of 0 is 1
9 if (n === 0) {
10 return 1;
11 }
12
13 // Initialize result to store the complement
14 let result: number = 0;
15
16 // Process each bit of n from right to left
17 let bitPosition: number = 0;
18 while (n > 0) {
19 // Get the least significant bit of n
20 const currentBit: number = n & 1;
21
22 // Flip the bit (XOR with 1) and place it at the correct position
23 const flippedBit: number = currentBit ^ 1;
24 result |= flippedBit << bitPosition;
25
26 // Move to the next bit
27 n >>= 1;
28 bitPosition++;
29 }
30
31 return result;
32}
33
Time and Space Complexity
The time complexity is O(log n)
, where n
is the given decimal number. This is because the while loop iterates through each bit of the number n
. Since n
is right-shifted by 1 position in each iteration (n >>= 1
), the loop runs for the number of bits in n
, which is approximately log₂(n)
times.
The space complexity is O(1)
. The algorithm only uses a constant amount of extra space with variables ans
and i
, regardless of the input size. No additional data structures that scale with input size are used.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Forgetting the Special Case for n = 0
Issue: Without handling n = 0
separately, the while loop never executes (since the condition n > 0
is false), resulting in returning 0
instead of the correct answer 1
.
Incorrect Code:
def bitwiseComplement(self, n: int) -> int:
result = 0
bit_position = 0
while n > 0: # This loop never runs when n = 0
flipped_bit = (n & 1) ^ 1
result |= flipped_bit << bit_position
bit_position += 1
n >>= 1
return result # Returns 0 for input 0, but should return 1
Solution: Always check for the edge case where n = 0
at the beginning of the function.
Pitfall 2: Using Fixed-Width Bit Manipulation
Issue: Attempting to use a fixed number of bits (like 32 bits) and XORing with a mask can lead to unnecessary leading 1s in the result.
Incorrect Code:
def bitwiseComplement(self, n: int) -> int:
# Wrong approach: XOR with all 1s for 32 bits
return n ^ 0xFFFFFFFF # This gives wrong answer for small numbers
For n = 5
(binary 101
), this would XOR with 11111111111111111111111111111111
, giving 11111111111111111111111111111010
instead of just 010
.
Solution: Process only the actual bits present in the number by iterating through them, as shown in the correct solution.
Pitfall 3: Incorrect Operator Precedence
Issue: Forgetting that bitwise AND (&
) has lower precedence than XOR (^
) without parentheses can lead to incorrect bit extraction.
Incorrect Code:
flipped_bit = n & 1 ^ 1 # This is interpreted as n & (1 ^ 1) = n & 0
This evaluates as n & (1 ^ 1)
which equals n & 0
, always giving 0
.
Solution: Use proper parentheses to ensure correct evaluation order:
flipped_bit = (n & 1) ^ 1 # Extract bit first, then flip
Pitfall 4: Using Signed Integer Operations Incorrectly
Issue: In some languages, using the NOT operator (~
) directly can cause issues with signed integers, producing negative numbers due to two's complement representation.
Incorrect Code:
def bitwiseComplement(self, n: int) -> int:
return ~n # This returns negative numbers in Python
For n = 5
, ~5
returns -6
in Python, not 2
.
Solution: Build the complement bit by bit, or if using NOT operator, mask the result appropriately to get only the relevant bits.
# Alternative correct approach using mask
def bitwiseComplement(self, n: int) -> int:
if n == 0:
return 1
mask = n
mask |= mask >> 1
mask |= mask >> 2
mask |= mask >> 4
mask |= mask >> 8
mask |= mask >> 16
return n ^ mask
A person thinks of a number between 1 and 1000. You may ask any number questions to them, provided that the question can be answered with either "yes" or "no".
What is the minimum number of questions you needed to ask so that you are guaranteed to know the number that the person is thinking?
Recommended Readings
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
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!