Medium
题目描述
n 位格雷码序列是一个由 2^n 个整数组成的序列,其中:
- 每个整数都在范围 [0, 2^n - 1] 内(含 0 和 2^n - 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
解题思路
格雷编码的构造可以通过以下几种方法实现:
方法一:递归构造法(推荐)
观察格雷码的构造规律:
- 1位格雷码:[0, 1]
- 2位格雷码:[0, 1, 3, 2],即在1位基础上,前半部分保持不变,后半部分为前半部分的逆序并在最高位加1
- 3位格雷码:[0, 1, 3, 2, 6, 7, 5, 4],同样遵循此规律
具体构造过程:
- 对于 n=1,返回 [0, 1]
- 对于 n>1,先构造 n-1 位的格雷码
- 将 n-1 位格雷码的逆序添加到结果末尾,并在每个数的第 n 位(从右数)设置为1
方法二:公式法
可以直接使用格雷码的数学公式:第 i 个格雷码 = i ^ (i » 1),其中 ^ 表示异或运算。
方法三:回溯法
通过深度优先搜索,每次尝试翻转一位,确保生成的序列满足格雷码的性质。
递归构造法思路清晰,实现简单,是最常用的方法。
代码实现
class Solution {
public:
vector<int> grayCode(int n) {
if (n == 1) {
return {0, 1};
}
vector<int> prev = grayCode(n - 1);
vector<int> result = prev;
int highBit = 1 << (n - 1);
for (int i = prev.size() - 1; i >= 0; i--) {
result.push_back(prev[i] + highBit);
}
return result;
}
};
class Solution:
def grayCode(self, n: int) -> List[int]:
if n == 1:
return [0, 1]
prev = self.grayCode(n - 1)
result = prev[:]
high_bit = 1 << (n - 1)
for i in range(len(prev) - 1, -1, -1):
result.append(prev[i] + high_bit)
return result
public class Solution {
public IList<int> GrayCode(int n) {
if (n == 1) {
return new List<int> {0, 1};
}
IList<int> prev = GrayCode(n - 1);
List<int> result = new List<int>(prev);
int highBit = 1 << (n - 1);
for (int i = prev.Count - 1; i >= 0; i--) {
result.Add(prev[i] + highBit);
}
return result;
}
}
/**
* @param {number} n
* @return {number[]}
*/
var grayCode = function(n) {
const result = [0];
for (let i = 0; i < n; i++) {
const size = result.length;
for (let j = size - 1; j >= 0; j--) {
result.push(result[j] | (1 << i));
}
}
return result;
};
复杂度分析
| 复杂度类型 | 递归构造法 |
|---|---|
| 时间复杂度 | O(2^n) |
| 空间复杂度 | O(2^n) |
说明:
- 时间复杂度:需要生成 2^n 个格雷码,每个码的生成时间为 O(1)
- 空间复杂度:需要存储 2^n 个整数,递归栈深度为 O(n),总空间复杂度为 O(2^n)
相关题目
- . 1-bit and 2-bit Characters (Easy)