格雷码是一种数字排序系统,其中的所有相邻整数在它们的二进制数字表示中只有一个数字不同。现要求打印出二进制比特数是n的所有格雷码。例如,n=2,所有的格雷码是0,1,3,2(对应二进制表示是00,01,11,10)。
思路一:
如果仔细观察格雷码的规律,可以发现,对于n比特的格雷码,前2^(n-1)个格雷码的前n-1比特和后2^(n-1)个格雷码的前n-1比特是对称的,前2^(n-1)个格雷码的第n比特和后2^(n-1)个格雷码的第n比特是相反的。例如,3比特的格雷码,如下所示:
0-0-0
0-0-1
0-1-1
0-1-0
1-1-0
1-1-1
1-0-1
1-0-0
可以发现,前4个格雷码的前2个比特和后四个格雷码的前2个比特是对称的,前4个格雷码的第3个比特和后四个格雷码的第3个比特是相反的。
有了这个规律,我们可以借助栈和队列来做这个题。设stack1存了所有的j比特格雷码。现在创建一个stack1的副本stack2,把stack2里所有格雷码都pop到另外一个队列queue里,然后依次从队列头部取元素,把这个元素和(1<<(j-1))进行异或,把异或结果push到stack1里。这个时候stack1里就存有所有的(j+1)比特格雷码。
vector<int> grayCode(int n) {
vector<int> vec;
vec.push_back(0);
if(n==0) return vec;
vec.push_back(1); // if n==1, vec=[0,1]
if(n>1) // if n>1
for(int i=1; i<n; i++)
{
int sz = vec.size();
for(int j=sz-1; j>=0; j--)
{
int num = vec[j];
num = num|(1<<i);
vec.push_back(num);
}
}
return vec;
}
思路二:
The tricky part of this question is to recognize the recursive structure here. For n = 0, sol = [0], that’s the base case. For recursive step, let’s take n = 2 and n = 3 as examples. n = 2, sol = [0, 1, 3, 2]; n = 3, sol = [0, 1, 3, 2, 6, 7, 5, 4]. Look at these two solutions, we see when n = 3, we add 4 more elements [6, 7, 5, 4] and they are just [2+4, 3+4, 1+4, 0+4]. That is sol(n+1) = sol(n) + [ reverse(sol(n)) + 2^(n) ].
class Solution {
public:
vector<int> grayCode(int n) {
if(n == 0) {
vector<int> sol;
sol.push_back(0);
return sol;
} else {
vector<int> previous = grayCode(n - 1);
vector<int> sol(previous);
for(int i = previous.size() - 1; i >= 0; --i) {
sol.push_back((int)pow(2.0, n - 1) + previous[i]);
}
return sol;
}
}
};