格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异。
给定一个代表编码总位数的非负整数 n,打印其格雷编码序列。格雷编码序列必须以 0 开头。
示例 1:
输入: 2 输出:[0,1,3,2]
解释: 00 - 0 01 - 1 11 - 3 10 - 2 对于给定的 n,其格雷编码序列并不唯一。 例如,[0,2,3,1]
也是一个有效的格雷编码序列。 00 - 0 10 - 2 11 - 3 01 - 1
示例 2:
输入: 0 输出:[0] 解释: 我们定义
格雷编码序列必须以 0 开头。给定
编码总位数为n 的格雷编码序列,其长度为 2n
。当 n = 0 时,长度为 20 = 1。 因此,当 n = 0 时,其格雷编码序列为 [0]。
1 #include"_000库函数.h" 2 3 //使用二进制转格雷码 4 class Solution { 5 public: 6 vector<int> grayCode(int n) { 7 vector<int>res; 8 for (int i = 0; i < pow(2, n); ++i) {//pow(2,n)种情况 9 res.push_back((i >> 1) ^ i);//二进制转格雷码 10 } 11 return res; 12 } 13 }; 14 15 //镜面排列 16 // Mirror arrangement 17 class Solution { 18 public: 19 vector<int> grayCode(int n) { 20 vector<int> res{ 0 }; 21 for (int i = 0; i < n; ++i) { 22 int size = res.size(); 23 for (int j = size - 1; j >= 0; --j) { 24 res.push_back(res[j] | (1 << i)); 25 } 26 } 27 return res; 28 } 29 }; 30 //维基百科上还有一条格雷码的性质是直接排列, 31 //以二进制为0值的格雷码为第零项,第一项改变最右边的位元, 32 //第二项改变右起第一个为1的位元的左边位元,第三、四项方法同第一、二项, 33 //如此反复,即可排列出n个位元的格雷码。根据这条性质也可以写出代码,不过相比前面的略微复杂, 34 //代码如下: 35 36 // Direct arrangement 37 class Solution { 38 public: 39 vector<int> grayCode(int n) { 40 vector<int> res{ 0 }; 41 int len = pow(2, n); 42 for (int i = 1; i < len; ++i) { 43 int pre = res.back(); 44 if (i % 2 == 1) { 45 pre = (pre & (len - 2)) | ((~pre) & 1); 46 } 47 else { 48 int cnt = 1, t = pre; 49 while ((t & 1) != 1) { 50 ++cnt; 51 t >>= 1; 52 } 53 if ((pre & (1 << cnt)) == 0) pre |= (1 << cnt); 54 else pre &= ~(1 << cnt); 55 } 56 res.push_back(pre); 57 } 58 return res; 59 } 60 }; 61 62 63 //使用最笨的方法 64 class Solution { 65 public: 66 vector<int> grayCode(int n) { 67 vector<int> res{ 0 }; 68 unordered_set<int> s; 69 stack<int> st; 70 st.push(0); 71 s.insert(0); 72 while (!st.empty()) { 73 int t = st.top(); st.pop(); 74 for (int i = 0; i < n; ++i) { 75 int k = t; 76 if ((k & (1 << i)) == 0) k |= (1 << i); 77 else k &= ~(1 << i); 78 if (s.count(k)) continue; 79 s.insert(k); 80 st.push(k); 81 res.push_back(k); 82 break; 83 } 84 } 85 return res; 86 } 87 };