Leetcode#89 Gray Code

原题地址

二进制码 -> 格雷码:从最右边起,依次与左边相邻位异或,最左边一位不变。例如:

二进制: 1 0 0 1 1 1 0
|||||||
格雷码: 1 1 0 1 0 0 1

从二进制到格雷码有一个残暴公式: a ^ (a << 1)

格雷码 -> 二进制码:从左边第二位开始,依次与左边相邻已经解码位异或,最左边一位不变。例如:

格雷码: 1 1 0 1 0 0 1
1| | | | | |
1 0 | | | | |
1 0| | | | |
1 0 0 | | | |
1 0 0| | | |
1 0 0 1 | | |
1 0 0 1| | |
1 0 0 1 1 | |
1 0 0 1 1| |
1 0 0 1 1 1 |
1 0 0 1 1 1|
1 0 0 1 1 1 0
二进制: 1 0 0 1 1 1 0

可惜从格雷码到二进制没有残暴公式

如何从一个格雷码生成下一个格雷码呢?规则如下:

1. 从0开始

2. 翻转最右位(0变1,1变0)

3. 翻转最右边是1的左边那一位,比如100110 -> 100010

4. 回到2

比如要生成4bit的格雷码,按照上面的规则:

步骤  格雷码      编号
1 0 0 0 0 (1)
|
2 0 0 0 1 (2)
|
3 0 0 1 1 (3)
|
2 0 0 1 0 (4)
|
3 0 1 1 0 (5)
|
2 0 1 1 1 (6)
|
3 0 1 0 1 (7)
|
2 0 1 0 0 (8)
|
3 1 1 0 0 (9)
|
2 1 1 0 1 (10)
|
3 1 1 1 1 (11)
|
2 1 1 1 0 (12)
|
3 1 0 1 0 (13)
|
2 1 0 1 1 (14)
|
3 1 0 0 1 (15)
|
2 1 0 0 0 (16)

代码:

 1 vector<int> grayCode(int n) {
 2   vector<int> res;
 3   int ub = (1 << n) - 1;
 4   int c = 0;
 5 
 6   for (int i = 0; i <= ub; i++) {
 7     c = (i & 1) ? c ^ 1 : c ^ ((c & -c) << 1);
 8     res.push_back(c);
 9   }
10 
11   return res;
12 }
原文地址:https://www.cnblogs.com/boring09/p/4248264.html