Problem#
Given a non-negative integer n
, find the position of the rightmost unset (zero) bit in its binary representation.
Positions in this page are 1-based (i.e., least-significant bit has position 1
). Return -1
if no unset bit exists in the considered word (or 0
for a mask result — see each method).
Examples#
Example 1#
1
2
Input: n = 11 # 0b1011
Output: 2
Example 2#
1
2
Input: n = 6 # 0b110
Output: 1
Example 3#
1
2
Input: n = 13 # 0b1101
Output: 2
Similar Problems
Solution#
We present three approaches: isolate mask using ~n & (n+1)
, scan bits, and a logarithm-based variant. Method 1 is preferred.
Intuition#
Adding 1
to n
flips the least-significant unset bit to 1
and clears any lower set bits. Bitwise ~n
turns unset bits to 1
. Intersection ~n & (n+1)
therefore isolates the rightmost unset bit as a mask.
Approach#
If n
has all bits set for the considered word width, there may be no unset bit — decide on sentinel (-1
for position).
Compute mask = (~n) & (n + 1)
.
To obtain 1-based position from mask
, compute the index of the single set bit in mask
.
Edge cases:
n == ~0u
for fixed-width words → no unset bits (return -1
).
Code#
Cpp
Go
Java
Python
1
2
3
4
5
6
7
8
class Solution {
public :
int rightmost_unset_pos(unsigned int n) {
unsigned int mask = (~ n) & (n + 1u );
if (mask == 0u ) return - 1 ; // no unset bit in this word
return __builtin_ctz (mask) + 1 ;
}
};
1
2
3
4
5
6
7
8
9
package main
import "math/bits"
func RightmostUnsetPos (n uint32 ) int {
mask := (^n ) & (n + 1 )
if mask == 0 { return - 1 }
return bits .TrailingZeros32 (mask ) + 1
}
1
2
3
4
5
6
7
class Solution {
public int rightmostUnsetPos (int n) {
int mask = (~ n) & (n + 1);
if (mask == 0) return - 1;
return Integer.numberOfTrailingZeros (mask) + 1;
}
}
1
2
3
4
5
6
class Solution :
def rightmost_unset_pos (self, n: int) -> int:
mask = (~ n) & (n + 1 )
if mask == 0 :
return - 1
return mask. bit_length()
Complexity#
⏰ Time complexity: O(1)
— bitwise operations on fixed-size words.
🧺 Space complexity: O(1)
.
Method 2 — Right-to-left scan#
Intuition#
Check bits from LSB moving left until an unset bit (0
) is found.
Approach#
If considering infinite-width integers, n
always has unset bits; for fixed-width, check full width.
Initialize pos = 1
.
While (n & 1) == 1
: n >>= 1
, pos += 1
.
Return pos
.
Code#
Cpp
Go
Java
Python
1
2
3
4
5
6
7
8
class Solution {
public :
int rightmost_unset_scan(unsigned int n) {
int pos = 1 ;
while ((n & 1u ) == 1u ) { n >>= 1 ; ++ pos; }
return pos;
}
};
1
2
3
4
5
6
7
8
func RightmostUnsetScan (n uint ) int {
pos := 1
for (n & 1 ) == 1 {
n >>= 1
pos ++
}
return pos
}
1
2
3
4
5
6
7
class Solution {
public int rightmostUnsetScan (int n) {
int pos = 1;
while ((n & 1) == 1) { n >>= 1; pos++ ; }
return pos;
}
}
1
2
3
4
5
6
7
class Solution :
def rightmost_unset_scan (self, n: int) -> int:
pos = 1
while (n & 1 ) == 1 :
n >>= 1
pos += 1
return pos
Complexity#
⏰ Time complexity: O(b)
where b
is the number of consecutive trailing set bits.
🧺 Space complexity: O(1)
.
Method 3 — Logarithm on isolated mask (not recommended)#
Intuition#
If mask = (~n) & (n+1)
isolates the unset-bit as a power-of-two, then position = 1 + log2(mask)
.
Approach#
Compute mask = (~n) & (n+1)
.
Compute pos = 1 + floor(log2(mask))
(avoid floating rounding issues).
Code#
Cpp
Java
Python
1
2
3
4
5
int rightmost_unset_log (unsigned int n) {
unsigned int mask = (~ n) & (n + 1u );
if (mask == 0u ) return - 1 ;
return 1 + static_cast < int > (std:: log2(mask));
}
1
2
3
4
5
int rightmostUnsetLog (int n) {
int mask = (~ n) & (n + 1);
if (mask == 0) return - 1;
return 1 + (int )(Math.log (mask) / Math.log (2));
}
1
2
3
4
5
6
def rightmost_unset_log (n: int) -> int:
mask = (~ n) & (n + 1 )
if mask == 0 :
return - 1
from math import log2
return 1 + int(log2(mask))
Complexity#
⏰ Time complexity: O(1)
.
🧺 Space complexity: O(1)
.
Notes & References#
Method 1 is robust and efficient; prefer platform builtins for trailing-zero counts when available.
Source examples are listed in source_links
in frontmatter.