Given a non-negative integer x, find the next higher integer that has the same number of set bits (1s) in its binary representation. If no higher integer exists (i.e., x is the largest permutation of its set bits), the behavior depends on application — typically iteration stops.
This is a classic bit-fiddling trick that computes the next lexicographic bit permutation with the same popcount. The expression below produces the result in constant time for fixed-width unsigned integers:
1
2
3
a = x & -x
b = a + x
r = b | (((x ^ b) >> 2) / a)
Below we explain why this works and give a few implementations.
Isolate the rightmost set-bit run in x. The next higher number is produced by moving the rightmost contiguous block of 1s one position to the left and placing the remaining 1s in the lowest possible positions.
classSolution {
public:unsignedint next_with_same_popcount(unsignedint x) {
if (x ==0) return0u;
unsignedint a = x &-x;
unsignedint b = x + a;
unsignedint c = ((x ^ b) >>2) / a;
return b | c;
}
};
classSolution {
publicintnextWithSamePopcount(int x) {
if (x == 0) return 0;
int a = x &-x;
int b = x + a;
int c = ((x ^ b) >>> 2) / a; // unsigned shiftreturn b | c;
}
}
1
2
3
4
5
6
7
8
classSolution:
defnext_with_same_popcount(self, x: int) -> int:
if x ==0:
return0 a = x &-x
b = x + a
c = ((x ^ b) >>2) // a
return b | c
Treat the bitstring as an array of bits and compute the next lexicographic permutation with the same number of 1s using a standard next-permutation approach: find the pivot (a 1 followed by a 0 to its left), swap, and right-adjust the suffix.
unsignedintnext_with_same_popcount_slow(unsignedint x) {
if (x ==0) return0u;
unsignedint t = x;
int pos =0;
// find first zero that has a one somewhere to its right
while ((t &1u) ==1u) { t >>=1; pos++; }
while ((t &1u) ==0u) { t >>=1; pos++; }
// pos now points to the bit to flip
unsignedint mask = (1u<< pos) -1u;
unsignedint ones = x & mask;
// clear lower bits and set the bit at pos
unsignedint res = (x &~mask) | (1u<< pos);
// place ones-1 in the lowest positions
res |= (ones >>1);
return res;
}