【题目概要】
89. 格雷编码
格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异。
给定一个代表编码总位数的非负整数 n,打印其格雷编码序列。即使有多个不同答案,你也只需要返回其中一种。
格雷编码序列必须以 0 开头。
示例 1:
输入: 2
输出: [0,1,3,2]
解释:
00 - 0
01 - 1
11 - 3
10 - 2
对于给定的 n,其格雷编码序列并不唯一。
例如,[0,2,3,1] 也是一个有效的格雷编码序列。
00 - 0
10 - 2
11 - 3
01 - 1
示例 2:
输入: 0
输出: [0]
解释: 我们定义格雷编码序列必须以 0 开头。
给定编码总位数为 n 的格雷编码序列,其长度为 2n。当 n = 0 时,长度为 20 = 1。
因此,当 n = 0 时,其格雷编码序列为 [0]。
【思路分析】
- 格雷码解法參考文獻
- 利用递归的思想來生成格雷码——2位格雷码:00 01 11 10,3位格雷码则是在2位基础上,加上
0+之前的n位,以及1+之前的n位——000 001 011 010 || 100 101 111 110
- 二进制——格雷码的转换关系
给定的是格雷码的位数n,则格雷码共有2^n^的个数,且每一个格雷码都是可以从0-2^n^的数直接转换过来
- 对n位二进制的码字,从右到左,以0到n-1编号
- 如果二进制码字的第i位和i+1位相同,则对应的格雷码的第i位为0,否则为1(当i+1=n时,二进制码字的第n位被认为是0,即第n-1位不变)
- 从左往右,两两亦或,最高位左边默认都是0
- (Gi = Bi ^ Bi+1)(n-1 > i >= 0)
- 格雷码——二进制
从左往右两两亦或,从左边的第二位开始,最高位不变,因为最高位之前是由0异或得到,就是本身,
以上操作,相当于上面步骤重新执行一次,返回原值
(Bi = Gi ^ Bi+1)(n-1 > i >= 0),上一次的结果对下一次有影响
验证和上面的计算方式相同
【小贴士】
异或可以進行交換律、結合律
任意數 ^ 0 = 本身
任意數 ^ 1 = 每一位取反
任意數 ^ 1 ^ 1 = 本身
任意數 ^ 任意數 = 0
【代码示例】
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* grayCode(int n, int* returnSize){
*returnSize = pow(2, n);// 1<<n
int *re = (int*)malloc(sizeof(int)*(*returnSize));
for(int graym=0; graym<*returnSize; graym++)
{
re[graym] = graym ^ graym >> 1;
}
return re;
}
// 二進制到格雷碼:從右到左异或,保留最高位相同
// 格雷碼到二進制:從左第二位,和左邊的^,每次的結果對下一位有影响