LeetCode-89-格雷编码
格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异。
给定一个代表编码总位数的非负整数 n,打印其格雷编码序列。格雷编码序列必须以 0 开头。
示例 1:
1 | 输入: 2 |
对于给定的 n,其格雷编码序列并不唯一。
例如,[0,2,3,1] 也是一个有效的格雷编码序列。
1 | 00 - 0 |
示例 2:
1 | 输入: 0 |
Solution1
动态规划法:
格雷码可以通过在当前的部分格雷码通过复制这一部分上下翻转次序后,使翻转后的部分通过新增加的最高位都转换为1来得到。
例如当前的部分序列为:1
200
01
翻转后为1
201
00
往每个数字前面增加一位前导零组合成新的部分格雷码:1
2
3
4000
001
001
000
将翻转后的数字的前导零置为1:1
2
3
4000
001
101
100
这一新的序列也是格雷码序列。
通过翻转n次,将得到长度为n全部的格雷码序列。
1 | class Solution { |
Solution2:
直接构造法:
维基百科中生成格雷码的步骤为:
以二进制为 0 值的格雷码为第零项,第一项改变最右边的位元,第二项改变右起第一个为1的位元的左边位元,第三、四项方法同第一、二项,如此反复,即可排列出n个位元的格雷码。
以3为例:
1 | 000 初始值 |
代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class Solution {
public:
vector<int> grayCode(int n) {
vector<int> ans;
ans.push_back(0);
for(int k = 1; k < 1<<n; k++){
// 改变右起第一项。
if(k%2) ans.push_back(ans[k-1]^1);
// 改变右起第一个为1的位元的左边位元
else{
int c = 0;
int pre = ans[k-1];
while(((pre>>c) & 1) == 0) c++;
c++;
ans.push_back(pre^(1<<c));
}
}
return ans;
}
};
Solution3:
公式法:
当前第i项的二进制数的最高位保留,其它位是当前位和它的高一位进行异或操作。
1 | class Solution { |