Problem#
Find the position of the most-significant set bit (MSB) in the binary representation of a non-negative integer n
.
Positions are zero-based from the least-significant bit (LSB). For example:
n = 4 (0b100)
→ MSB position = 2
.
n = 99 (0b1100011)
→ MSB position = 6
.
Examples#
Example 1#
1
2
Input: n = 4
Output: 2
Example 2#
1
2
Input: n = 99
Output: 6
Solution#
Below are three approaches: naive scan, binary-search-like mask, and using builtins for leading-zero / bit-length.
Method 1 — Right-shift scan (naive)#
Intuition#
Shift n
right until it becomes 0
. The number of shifts performed is the MSB position.
Approach#
If n == 0
return -1
(no set bits) or a sentinel as required.
Initialize pos = 0
.
While (n >>= 1) != 0
: increment pos
.
Return pos
.
Code#
Cpp
Go
Java
Python
1
2
3
4
5
6
7
8
9
class Solution {
public :
int msb_pos(unsigned int n) {
if (n == 0 ) return - 1 ;
int pos = 0 ;
while (n >>= 1 ) ++ pos;
return pos;
}
};
1
2
3
4
5
6
7
8
9
10
package main
func MSBPos (n uint ) int {
if n == 0 { return - 1 }
pos := 0
for n >>= 1 ; n != 0 ; n >>= 1 {
pos ++
}
return pos
}
1
2
3
4
5
6
7
8
class Solution {
public int msbPos (int n) {
if (n == 0) return - 1;
int pos = 0;
while ((n >>= 1) != 0) pos++ ;
return pos;
}
}
1
2
3
4
5
6
7
8
9
class Solution :
def msb_pos (self, n: int) -> int:
if n == 0 :
return - 1
pos = 0
while n >> 1 :
n >>= 1
pos += 1
return pos
Complexity#
⏰ Time complexity: O(b)
, where b
is the number of bits (e.g., 32 or 64).
🧺 Space complexity: O(1)
.
Method 2 — Binary-search-like mask#
Intuition#
Check ranges of bit widths using masks (e.g., check high half of bits). Repeatedly narrow to the half that contains any set bit — this requires at most O(log b)
mask checks.
Approach#
Set low = 0
, high = w-1
for word width w
(e.g., 31 for 32-bit signed).
While high - low > 1
, compute mid = (high + low)/2
and a mask for bits mid+1..high
.
If (n & mask) != 0
then the MSB lies in the high half: set low = mid
; else high = mid
.
Return low
as the MSB position.
Code (sketch)#
C++#
1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public :
int msb_pos_binsearch(unsigned int n) {
if (n == 0 ) return - 1 ;
int low = 0 , high = 31 ; // assumes 32-bit word
while (high - low > 1 ) {
int mid = (high + low) / 2 ;
unsigned int mask = ((1u << (high - mid)) - 1u ) << (mid + 1 );
if (n & mask) low = mid; else high = mid;
}
return low;
}
};
Go (sketch)#
1
2
3
4
5
6
7
8
9
10
func MSBPosBinSearch (n uint32 ) int {
if n == 0 { return - 1 }
low , high := 0 , 31
for high - low > 1 {
mid := (high + low ) / 2
mask := ((uint32(1 ) << (high - mid )) - 1 ) << (mid + 1 )
if n & mask != 0 { low = mid } else { high = mid }
}
return low
}
Complexity#
⏰ Time complexity: O(log b)
(log of the bit-width).
🧺 Space complexity: O(1)
.
Method 3 — Use builtins (fast, recommended)#
Intuition#
Most platforms expose operations for counting leading zeros or bit-length. MSB position equals bit_length(n) - 1
or w - 1 - clz(n)
.
Approach#
Validate n != 0
then use a builtin (__builtin_clz
, Integer.numberOfLeadingZeros
, int.bit_length()
), then compute MSB position.
Code#
Cpp
Java
Python
1
2
3
4
int msb_pos_builtin (unsigned int n) {
if (n == 0 ) return - 1 ;
return 31 - __builtin_clz(n); // for 32-bit
}
1
2
3
4
int msbPos (int n) {
if (n == 0) return - 1;
return 31 - Integer.numberOfLeadingZeros (n);
}
1
2
3
4
def msb_pos (n: int) -> int:
if n == 0 :
return - 1
return n. bit_length() - 1
Complexity#
⏰ Time complexity: O(1)
for fixed-size words (builtin operations compile to a few CPU instructions).
🧺 Space complexity: O(1)
.
Notes & References#
Choose Method 3 when available — it’s simple and fast. Method 1 is portable and trivial. Method 2 can be useful in environments without clz
/bit_length
.
Sample runs and additional discussion originally from the referenced tutorial (see source_links
in frontmatter).