LeetCode——89.格雷编码

一、题目

n 位格雷码序列 是一个由 2n 个整数组成的序列,其中:
每个整数都在范围 [0, 2n - 1] 内(含 0 和 2n - 1)
第一个整数是 0
一个整数在序列中出现 不超过一次
每对 相邻 整数的二进制表示 恰好一位不同 ,且
第一个 和 最后一个 整数的二进制表示 恰好一位不同
给你一个整数 n ,返回任一有效的 n 位格雷码序列 。

示例 1:

输入:n = 2
输出:[0,1,3,2]
解释:
[0,1,3,2] 的二进制表示是 [00,01,11,10] 。

  • 00 和 01 有一位不同
  • 01 和 11 有一位不同
  • 11 和 10 有一位不同
  • 10 和 00 有一位不同
    [0,2,3,1] 也是一个有效的格雷码序列,其二进制表示是 [00,10,11,01] 。
  • 00 和 10 有一位不同
  • 10 和 11 有一位不同
  • 11 和 01 有一位不同
  • 01 和 00 有一位不同
    示例 2:

输入:n = 1
输出:[0,1]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/gray-code

二、格雷码转化方法

递归生成码表法

  • 这种方法基于格雷码是反射码的事实,利用递归的如下规则来构造:
  • 1位格雷码有两个码字
  • (n+1)位格雷码中的前2n个码字等于n位格雷码的码字,按顺序书写,加前缀0
  • (n+1)位格雷码中的后2n个码字等于n位格雷码的码字,按逆序书写,加前缀1
  • n+1位格雷码的集合 = n位格雷码集合(顺序)加前缀0 + n位格雷码集合(逆序)加前缀1
  • 如表所示
2位格雷码 3位格雷码 3位格雷码
00 000 0000
01 001 0001
11 011 0011
10 010 0010
110 0110
111 0111
101 0101
100 0100
1100
1101
1111
1110
1010
1011
1001
1000

异或转换法

二进制码→格雷码(编码):
此方法从对应的n位二进制码字中直接得到n位格雷码码字,步骤如下:

  • 对n位二进制的码字,从右到左,以0到n-1编号
  • 如果二进制码字的第i位和i+1位相同,则对应的格雷码的第i位为0,否则为1(当i+1=n时,二进制码字的第n位被认为是0,即第n-1位不变)
  • 公式表示: Gi =Bi⊕Bi+1(n-1 ≥ i ≥ 0)(G:格雷码,B:二进制码)

三、C语言解法

本解法采用了递归生成码表法的思路,在逆序赋值的时候直接加上前缀1

int* grayCode(int n, int* returnSize) {
   int *ret = (int *)malloc((1<<n)*sizeof(int));//申请2的n次方的int类型空间
   ret[0] = 0;//初始数组为0
   int retsize = 1;//数组大小初始为1,后面会不断的在前面的基础上进行迭代
   for(int i = 1;i<=n;i++){//迭代的次数为n次
    for(int j = retsize -1;j>=0;j--){
            ret[2*retsize - 1 -j] = ret[j]|(1<<(i-1));//格雷码后缀对称的特性,只需要在相对应的数组加上2的i-1次方就可以了
        }
        retsize <<= 1;//数组大小改变为原来的两倍
   }
    *returnSize = retsize;//返回数组大小
    return ret; //返回数组
}

你可能感兴趣的:(力扣,c,leetcode,算法)