【题目】
The gray code is a binary numeral system where two successive values differ in only one bit.
Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0.
For example, given n = 2, return [0,1,3,2]
. Its
gray code sequence is:
00 - 0 01 - 1 11 - 3 10 - 2
Note:
For a given n, a gray code sequence is not uniquely defined.
For example, [0,2,3,1]
is also a valid gray code sequence according
to the above definition.
For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that.
【题意】
格雷码是一个二进制数字集合,相邻两数间只有一个位元改变。
给定一个非负整数n代表的比特位的总数,打印格雷码序列。格雷码序列必须从0开始。
例如,给定n=2,返回[0,1,3,2]。它的格雷码序列为:
00 - 0 01 - 1 11 - 3 10 - 2
注意:
对于给定的n,格雷码序列不是唯一地。
例如,按上述定义[0,2,3,1]也是一个有效的格雷码序列。
现在,判定系统只能够判断基于格雷码序列的一个实例。我们对此深感抱歉。
【分析】
思路1:
格雷码 (Gray Code) 的定义请参考 wikipedia http://en.wikipedia.org/wiki/Gray_code。
- 自然二进制码转换为格雷码:
保留自然二进制码的最高位作为格雷码的最高位,格雷码次高位为二进制码的高位与次高位异或,其余各位与次高位的求法类似。
例如,将自然二进制码 1001,转换为格雷码的过程是:
保留最高位;然后将第 1 位的 1 和第 2 位的 0 异或,得到 1,作为格雷码的第 2 位;将第 2 位的 0 和第 3 位的 0 异或,得到 0,
作为格雷码的第 3 位;将第 3 位的 0 和第 4 位的 1 异或,得到 1,作为格雷码的第 4 位,最终,格雷码为 1101。
- 格雷码转换为自然二进制码:
保留格雷码的最高位作为自然二进制码的最高位,次高位为自然二进制高位与格雷码次高位异或,其余各位与次高位的求法类似。
例如,将格雷码 1000 转换为自然二进制码的过程是:
保留最高位 1,作为自然二进制码的最高位;然后将自然二进制码的第 1 位 1 和格雷码的第 2 位 0 异或,得到1,
作为自然二进制码的第 2 位;将自然二进制码的第 2 位 1 和格雷码的第 3 位 0 异或,得到 1,作为自然二进制码的第 3 位;
将自然二进制码的第 3 位 1 和格雷码的第 4 位 0 异或,得到 1,作为自然二进制码的第 4 位,最终,自然二进制码为 1111。
-
格雷码有数学公式,整数 n 的格雷码是
这题要求生成 n 比特的所有格雷码。最简单的方法,利用数学公式,对从 0~ 2^n - 1的所有整数,转化为格雷码。
思路2:
n 比特的格雷码,可以递归地从 n - 1 比特的格雷码生成。
n位元的格雷码可以从n-1位元的格雷码以上下镜射后加上新位元的方式快速的得到,如右图所示一般。
红色的最高位加一即保持不变。
蓝色的最高位加一;n = 1时原格雷码十进制加1 ; n = 2时 加2 ; n = 3时 加 4 ;n= 4时 加 8............
【代码1】
/********************************* * 日期:2014-01-23 * 作者:SJF0115 * 题号: Gray Code * 来源:http://oj.leetcode.com/problems/gray-code/ * 结果:AC * 来源:LeetCode * 总结: **********************************/ #include <iostream> #include <stdio.h> #include <vector> using namespace std; class Solution { public: //数学公式,时间复杂度 O(2^n),空间复杂度 O(1) vector<int> grayCode(int n) { int count = 1 << n; vector<int> code; for(int i = 0;i < count;i++){ code.push_back(binaryToGrayCode(i)); } return code; } private: int binaryToGrayCode(int n){ return n ^ (n >> 1); } }; int main() { Solution solution; vector<int> result; result = solution.grayCode(3); int n = result.size(); for(int i = 0;i < n;i++){ printf("%d ",result[i]); } printf("\n"); return 0; }
【代码2】
/********************************* * 日期:2014-01-23 * 作者:SJF0115 * 题号: Gray Code * 来源:http://oj.leetcode.com/problems/gray-code/ * 结果:AC * 来源:LeetCode * 总结: **********************************/ #include <iostream> #include <stdio.h> #include <vector> using namespace std; class Solution { public: //镜射排列 vector<int> grayCode(int n) { int i,j,count,c; vector<int> code; //初始为0位 code.push_back(0); for(i = 0;i < n;i++){ count = code.size(); c = 1 << i; //添加镜面反射的那一部分(最高位加1) //要反着遍历才能对称 for(j = count - 1;j >= 0;j--){ code.push_back(code[j] + c); } } return code; } }; int main() { Solution solution; vector<int> result; result = solution.grayCode(3); int n = result.size(); for(int i = 0;i < n;i++){ printf("%d ",result[i]); } printf("\n"); return 0; }
格雷码转二进制数
二进制码第n位 = 二进制码第(n+1)位+格雷码第n位。因为二进制码和格雷码皆有相同位数,所以二进制码可从最高位的左边位元取0,以进行计算。(注:遇到1+1时结果视为0)
例如: 格雷码0111,为4位数,所以其所转为之二进制码也必为4位数,因此可取转成之二进制码第五位为0,即0 b3 b2 b1 b0。
0+0=0,所以b3=0
0+1=1,所以b2=1
1+1取0,所以b1=0
0+1取1,所以b0=1
因此所转换为之二进制码为0101