跳到主要内容

89.格雷编码

· 阅读需 4 分钟

1、题干

n 位格雷码序列 是一个由 2n 个整数组成的序列,其中:
  • 每个整数都在范围 [0, 2n - 1] 内(含 02n - 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]

 

提示:

  • 1 <= n <= 16

格雷编码的生成方式有3种,直接计算、镜像对称构造、交替构造;可惜我一个都没推出来,这里做个简单记录。

2、直接计算

直接计算的公式是:G(n)=nn2G(n) = n \oplus \dfrac{n}{2}。其中 G(n)G(n) 表示第 nn 个格雷码。

该解法对应官解2

3、代码

var grayCode = function(n) {
const ret = [];
for (let i = 0; i < 1 << n; i++) {
ret.push((i >> 1) ^ i);
}
return ret;
};

4、镜像对称构造

  • 将前2k个格雷码去除首位二进制数并分成两半后具有镜像对称性。(如下图3位格雷码)
  • n位格雷码是将n-1位格雷码作为前半部分,将n-1位格雷码倒序遍历并在其二进制数之前添1作为后半部分。(如下图3位格雷码与2位格雷码关系)

image.png

该解法对应官解1

5、代码

var grayCode = function (n) {
const arr = [0, 1];
for (let i = 2; i <= n; i++) {
for (let j = arr.length - 1; j > -1; j--) {
arr.push(arr[j] | (1 << (i - 1)));
}
}
return arr;
};

6、交替构造

以3位格雷码为例:

  • n = 0 开始,按以下2步反复操作,即可得到所有格雷码
  • n 为偶数:翻转最低位得到下一个格雷码,如 000 变成 001
  • n 为奇数:把最右边的 1 左边的位翻转得到下一个格雷码,如 001 变成 011

实现略复杂,暂无代码,建议优先使用前2种方法生成