docs-isharkfly-com/algorithm/gray-code.md

89 lines
2.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 格雷编码Gray Code
> 🔔 参与讨论https://www.isharkfly.com/t/gray-code/15120
## 描述
格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个二进制的差异。
给定一个非负整数 `n` ,表示该代码中所有二进制的总数,请找出其格雷编码顺序。一个格雷编码顺序必须以 `0` 开始,并覆盖所有的 2n 个整数。
对于给定的 `n`,其格雷编码顺序并不唯一。
根据以上定义, `[0,2,3,1]` 也是一个有效的格雷编码顺序。
## 样例
给定 `n = 2` 返回 `[0,1,3,2]`。其格雷编码顺序为:
```
00 - 0
01 - 1
11 - 3
10 - 2
```
## 挑战
O(2n) 时间复杂度。
## 代码
```
/**
* 411 https://www.lintcode.com/problem/gray-code/description
*/
@Test
public void test0411GrayCode() {
int n = 2;
List<Integer> retArray = new ArrayList<>();
if (n == 0) {
retArray.add(0);
}
for (int i = 0; i < (2 << (n - 1)); i++) {
int g = i ^ (i / 2);
retArray.add(g);
}
System.out.println(retArray);
}
```
## 点评
你需要对 Java 的位运算之间的关系和数据结构有比较深的了解。
在计算机语言中,数字的存储是按照位存储的。比如说 int 数据类型,在 Java 中定义的是 32 位。
那么 int 能在 Java 中存储的 2 进制格式为:
0000 0000 0000 0000 0000 0000 0000 0000
这里一共是 8 组,一共是 32 位。
如果你希望了解 Java int 是如何在 2 进制中表示的你可以使用方法Integer.toBinaryString(0)
这个方法不会输出完整的 32 位字符串,你需要在前面补上 0。
【0】 转换为 2 进制为【0000 0000 0000 0000 0000 0000 0000 0000】
【2】 转换为 2 进制为【0000 0000 0000 0000 0000 0000 0000 0010】
【5】 转换为 2 进制为【0000 0000 0000 0000 0000 0000 0000 0101】
在这个题目中哟 2 个地方比较关键,第一个地方是需要循环多少次,就是 2 的 n 次方,应该是多少?第二个地方就是进行位运算了,你需要需要什么样的位运算符。
对于 2 的 n 次方的结果,基本上可以使用下面的公式 2 << (n-1),比如说 2 的 3 次方,那么就需要将 2 向左位移 2 位。
移动前:
【2】 转换为 2 进制为【0000 0000 0000 0000 0000 0000 0000 0010】
移动后
【0000 0000 0000 0000 0000 0000 0000 1000】这个 2 进制转换后的结果就是 【8】 正好是 2 的 3 次方。
随后,对 i 取整后进行一次异或运算就可以得到你要的结果的 2 进制结果了。