comments | difficulty | edit_url | rating | source | tags | |||
---|---|---|---|---|---|---|---|---|
true |
Medium |
1774 |
Weekly Contest 160 Q2 |
|
Given 2 integers n
and start
. Your task is return any permutation p
of (0,1,2.....,2^n -1)
such that :
<li><code>p[0] = start</code></li>
<li><code>p[i]</code> and <code>p[i+1]</code> differ by only one bit in their binary representation.</li>
<li><code>p[0]</code> and <code>p[2^n -1]</code> must also differ by only one bit in their binary representation.</li>
Example 1:
Input: n = 2, start = 3 Output: [3,2,0,1] Explanation: The binary representation of the permutation is (11,10,00,01). All the adjacent element differ by one bit. Another valid permutation is [3,1,0,2]
Example 2:
Input: n = 3, start = 2 Output: [2,6,7,5,4,0,1,3] Explanation: The binary representation of the permutation is (010,110,111,101,100,000,001,011).
Constraints:
<li><code>1 <= n <= 16</code></li>
<li><code>0 <= start < 2 ^ n</code></li>
We observe the arrangement in the problem, and find that in its binary representation, only one bit is different between any two (including the first and last) adjacent numbers. This kind of coding method is Gray code, which is a coding method we will encounter in engineering.
The rule for converting binary code to binary Gray code is to keep the highest bit of the binary code as the highest bit of the Gray code, and the second highest bit of the Gray code is the XOR of the highest bit and the second highest bit of the binary code. The rest of the Gray code is similar to the second highest bit.
Assume a binary number is represented as
Therefore, for an integer
int gray(x) {
return x ^ (x >> 1);
}
We can directly convert the integers
The time complexity is
class Solution:
def circularPermutation(self, n: int, start: int) -> List[int]:
g = [i ^ (i >> 1) for i in range(1 << n)]
j = g.index(start)
return g[j:] + g[:j]
class Solution {
public List<Integer> circularPermutation(int n, int start) {
int[] g = new int[1 << n];
int j = 0;
for (int i = 0; i < 1 << n; ++i) {
g[i] = i ^ (i >> 1);
if (g[i] == start) {
j = i;
}
}
List<Integer> ans = new ArrayList<>();
for (int i = j; i < j + (1 << n); ++i) {
ans.add(g[i % (1 << n)]);
}
return ans;
}
}
class Solution {
public:
vector<int> circularPermutation(int n, int start) {
int g[1 << n];
int j = 0;
for (int i = 0; i < 1 << n; ++i) {
g[i] = i ^ (i >> 1);
if (g[i] == start) {
j = i;
}
}
vector<int> ans;
for (int i = j; i < j + (1 << n); ++i) {
ans.push_back(g[i % (1 << n)]);
}
return ans;
}
};
func circularPermutation(n int, start int) []int {
g := make([]int, 1<<n)
j := 0
for i := range g {
g[i] = i ^ (i >> 1)
if g[i] == start {
j = i
}
}
return append(g[j:], g[:j]...)
}
function circularPermutation(n: number, start: number): number[] {
const ans: number[] = [];
for (let i = 0; i < 1 << n; ++i) {
ans.push(i ^ (i >> 1) ^ start);
}
return ans;
}
Since
Therefore, we can also directly convert the integers
The time complexity is
class Solution:
def circularPermutation(self, n: int, start: int) -> List[int]:
return [i ^ (i >> 1) ^ start for i in range(1 << n)]
class Solution {
public List<Integer> circularPermutation(int n, int start) {
List<Integer> ans = new ArrayList<>();
for (int i = 0; i < 1 << n; ++i) {
ans.add(i ^ (i >> 1) ^ start);
}
return ans;
}
}
class Solution {
public:
vector<int> circularPermutation(int n, int start) {
vector<int> ans(1 << n);
for (int i = 0; i < 1 << n; ++i) {
ans[i] = i ^ (i >> 1) ^ start;
}
return ans;
}
};
func circularPermutation(n int, start int) (ans []int) {
for i := 0; i < 1<<n; i++ {
ans = append(ans, i^(i>>1)^start)
}
return
}