Given a positive integer, print the next smallest and the next largest number that have the same number of 1 bits in their binary representation.
Example1:
Input: num = 2 (0b10)
Output: [4, 1] ([0b100, 0b1])
Example2:
Input: num = 1
Output: [2, -1]
Note:
1 <= num <= 2147483647
If there is no next smallest or next largest number, output -1.
Solutions
Solution 1: Bit Manipulation
First, let's consider how to find the first number that is larger than $num$ and has the same number of $1$s in its binary representation.
We can traverse the adjacent two binary bits of $num$ from low to high. If the lower bit is $1$ and the adjacent higher bit is $0$, then we have found a position where we can change the $0$ at this position to $1$ and change the $1$ at this position to $0$. Then we move all the remaining lower bits of $1$ to the lowest bit, so we get a number that is larger than $num$ and has the same number of $1$s in its binary representation.
Similarly, we can find the first number that is smaller than $num$ and has the same number of $1$s in its binary representation.
We can traverse the adjacent two binary bits of $num$ from low to high. If the lower bit is $0$ and the adjacent higher bit is $1$, then we have found a position where we can change the $1$ at this position to $0$ and change the $0$ at this position to $1$. Then we move all the remaining lower bits of $0$ to the lowest bit, so we get a number that is smaller than $num$ and has the same number of $1$s in its binary representation.
In implementation, we can use a piece of code to handle the above two situations uniformly.
The time complexity is $O(\log n)$, where $n$ is the size of $num$. The space complexity is $O(1)$.