Given two integers, n
and start
, generate a permutation of all 2^n
integers from 0
to 2^n - 1
such that:
start
.0
to 2^n - 1
must appear exactly once.
To solve this problem, first recognize that it asks for a circular permutation where each adjacent element (including the wrap-around from last to first) differs by a single bit. This is the definition of a Gray code sequence.
The brute-force approach would be to generate all possible permutations and check if they satisfy the bit-difference condition, but this is highly inefficient for larger n
(factorial time).
Instead, we recall that a Gray code for n
bits is a known sequence satisfying the adjacency property. The only twist is that the sequence must start at start
, not at 0
. We need to generate the Gray code and then rotate it so it starts at start
.
Here’s a step-by-step breakdown:
i
is i ^ (i >> 1)
. For all i
from 0
to 2^n - 1
, this produces a list where each adjacent pair differs by one bit.start
, XOR each element in the Gray code sequence with start
. This preserves the one-bit difference property, since XORing all elements by a constant shifts the sequence but doesn’t change the bit-difference property between consecutive elements.start
and covering all numbers from 0
to 2^n - 1
exactly once.
Suppose n = 2
and start = 3
.
Step 1: Generate standard 2-bit Gray code:
i = 0
: 0 ^ (0 >> 1) = 0
i = 1
: 1 ^ (1 >> 1) = 1 ^ 0 = 1
i = 2
: 2 ^ (2 >> 1) = 2 ^ 1 = 3
i = 3
: 3 ^ (3 >> 1) = 3 ^ 1 = 2
[0, 1, 3, 2]
.
start = 3
:
0 ^ 3 = 3
1 ^ 3 = 2
3 ^ 3 = 0
2 ^ 3 = 1
[3, 2, 0, 1]
.
3
to 2
: 3 ^ 2 = 1
(one bit)2
to 0
: 2 ^ 0 = 2
(one bit)0
to 1
: 0 ^ 1 = 1
(one bit)1
to 3
: 1 ^ 3 = 2
(one bit, wrap-around)Brute-force Approach:
2^n
elements and checking each for the one-bit property.O((2^n)!)
— factorial time, infeasible for even small n
.O(2^n)
to store a permutation.O(2^n)
time, since we generate each number once.start
: O(2^n)
time.O(2^n)
for the result list.This problem leverages the mathematical structure of Gray codes, which naturally satisfy the requirement that each consecutive number differs by one bit. By generating the Gray code and then XORing each element with the desired starting value, we efficiently construct a valid circular permutation in binary representation. This approach is elegant, avoids brute-force, and runs in optimal time and space.
class Solution:
def circularPermutation(self, n: int, start: int) -> List[int]:
result = []
for i in range(1 << n):
result.append(start ^ (i ^ (i >> 1)))
return result
class Solution {
public:
vector<int> circularPermutation(int n, int start) {
vector<int> result;
int size = 1 << n;
for (int i = 0; i < size; ++i) {
result.push_back(start ^ (i ^ (i >> 1)));
}
return result;
}
};
class Solution {
public List<Integer> circularPermutation(int n, int start) {
List<Integer> result = new ArrayList<>();
int size = 1 << n;
for (int i = 0; i < size; ++i) {
result.add(start ^ (i ^ (i >> 1)));
}
return result;
}
}
var circularPermutation = function(n, start) {
const result = [];
for (let i = 0; i < (1 << n); i++) {
result.push(start ^ (i ^ (i >> 1)));
}
return result;
};