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