0
点赞
收藏
分享

微信扫一扫

格雷编码(2022-1-8)每日一题

格雷编码(2022-1-8)

文章目录


leetcode原题

题目如下:

n 位格雷码序列 是一个由 2n 个整数组成的序列,其中:

  • 每个整数都在范围 [0, 2n - 1] 内(含 0 和 2n - 1)
  • 第一个整数是 0
  • 一个整数在序列中出现 不超过一次
  • 每对 相邻 整数的二进制表示 恰好一位不同 ,且
  • 第一个 和 最后一个 整数的二进制表示 恰好一位不同

给你一个整数 n ,返回任一有效的 n 位格雷码序列 。

示例 1:

你需要先清楚一下几点:

二进制位运算

解题原理:套公式 时间复杂度 O(2n) 空间复杂度 O(1) )
g ( i ) = b ( i + 1 ) ⊕ b ( i ) , 0 ≤ i < n g(i)=b(i+1)⊕b(i), 0≤i<n g(i)=b(i+1)b(i),0i<n

其 中 ⊕ 是 按 位 异 或 运 算 , g ( i ) 和 b ( i ) 分 别 表 示 g 和 b 的 第 i 位 , 且 b ( n ) = 0 其中 \oplus 是按位异或运算,g(i) 和 b(i) 分别表示 g 和 b 的第 i 位,且 b(n)=0 g(i)b(i)gbib(n)=0

var grayCode = function(n) {
    // n决定了二进制的位数
    let res = []
    for(let i = 0; i < 1 << n; i++){
        res.push((i >> 1) ^ i)
    }
    return res
};

二进制找规律

另一种好理解的思路:
前后对称,直接上图(时间复杂度 O(2n) 空间复杂度 O(1) )

  1. 格雷编码G(n)前面 2*(i-1)位是在G(n-1)的基础上,在二进制位前面补0!
  2. 后边的剩下的一半就是将前面的对称过来,把前置位0转换成1即可!
  3. 拼接 G(n) 和 R(n) 即可得到结果

根据以上规律,我们可以通过之前阶的格雷码推出之后任意阶的格雷码

// 官方题解
var grayCode = function(n) {
    const res = [0];
    for (let i = 1; i <= n; i++) {
        const m = ret.length;
        for (let j = m - 1; j >= 0; j--) {
            ret.push(ret[j] | (1 << (i - 1)));
        }
    }
    return res;
};

递归

也可以换一种思路,采用十进制表示

n = 2

[0, 1, 3, 2]

n = 3

[0, 1, 3, 2, 6, 7, 5, 4]

可以看出 2 - 6,3 - 7,1 - 5,0 - 4,在对称的位置前后相差4,而4其实是2n-1,也就是22得来的。

那么只需要进行如下操作:

  1. 拿到上一次的格雷码也就是G(n-1)
  2. 反转并加上2n-1
  3. 拼接上G(n-1),即可得到G(n)
// 自己写的
var grayCode = function(n) {
  if (n === 0) {
    return [0]
  }
  if (n === 1) {
    return [0, 1]
  }
  let formerGrayCode = grayCode(n - 1);
  return [
    ...formerGrayCode,
    ...formerGrayCode.reverse().map(v => v + Math.pow(2, n - 1)),
  ];
}
举报

相关推荐

0 条评论