题目描述
格雷码是一个二进制数系统,满足相邻两个数只有一位不同。
给定一个非负整数 n,表示格雷码的位数,请输出一个合法的格雷码序列。
格雷码序列必须以0开始。
例如,给定 n=2,返回 [0, 1, 3, 2]
。它表示的格雷码序列是:
00 - 0
01 - 1
11 - 3
10 - 2
注意:对于一个给定的 n,格雷码序列并不唯一。例如 [0, 2, 3, 1]
也是一个合法的格雷码序列。
算法
(构造) O(2n)
我们可以先打表找规律,随便找出一种格雷码的构造方法即可。
我们可以递归构造:
- 先构造 n=1,即只有一位的格雷码序列:
[0, 1]
; - 假设我们已经构造好了 n=k时的格雷码序列 Sk,我们可以利用它来构造 Sk+1:
(1) Sk+1的前一半:将 Sk 中的每个数开头补上1;
(2) Sk+1的后一半,将 Sk 变成逆序,然后在每个数开头补上0;
时间复杂度分析:对于给定的 n,计算量是 2(1+2+4+…+2n−1)=2n+1−2,所以时间复杂度是 O(2n)。
C++ 代码
class Solution {
public:
vector<int> grayCode(int n) {
vector<int> res;
res.push_back(0);
int t = 1;
while (n -- )
{
vector<int> newRes;
for (int i = 0; i < res.size(); i ++ )
newRes.push_back(res[i]);
for (int i = res.size() - 1; i >= 0; i -- )
newRes.push_back(t + res[i]);
res = newRes;
t *= 2;
}
return res;
}
};
其实newRes可以不用开,直接加在后面就可以;
class Solution { public: vector<int> grayCode(int n) { vector<int> res; res.push_back(0); int t = 0; while (n -- ) { int n = res.size(); for (int i = n - 1; i >= 0; i --) { res.push_back(res[i] + (1 << t)); } t += 1; } return res; } };
不错,可以省掉。