通过万岁!!!
- 题目:先不用管什么是格雷编码。题目的意思就是给你一个n,然后返回一个数组,这个数组里面的数是从0到2的n次方-1。然后在了解一下什么是各类编码,要求这这个数组中的数转成二进制表示有满足几个条件。
- 第一个是0
- 每个数只出现一次
- 转换成二进制以后,相邻两个数之间只能由一位不同
- 第一个和最有一个的二进制表示也是只有一位不同。
- 给出例子[00,01,11,10],第一个数是0,第二个是01表示1,与00只有一个位置不同,第三个数11与第二个数只有一个不同,最后一个是10与第三个一个位置不同,与第一个也是一个位置不同。这样就是一个格雷编码。其实听这个例子,会觉得题目比较难。
- 思路:这里面是有一个技巧的,我们可以发现将上面数组进行拆分[00,01;;;;;;11,10],这里用多个分号进行拆分。然后我们去掉第一位[0,1;;;;;;1,0],发现了吗。对称的,也就是说而右边的就是左边的对称之后前面加个1。并且明确数组长度是2的n次方。
- 技巧:
- 主要是找到如何生成这个数组。然后找到生成的规律,下面是规律
- 首先n=1的时候,数组是[0,1],长度为2的1次方。n=2的时候,数组长度为2的2次方。因此我们可以直接定义好数组长度。
- 然后就是上面说的每次在前面加个1,其实就是十进制加了2的n-1次方。
- 接下来就是从什么位置开始加以及前面的数怎么找。可以发现,开始位置也是2的n-1次方,从开始位置依次-1就是对称之后前面的数。
- 注意:
- 代码中1<<i就表示2的i次方。
- 并且<<运算符的优先级非常低,所以需要加括号。例如这里(1 << (i - 1)),如果这是一个整体,就加一个括号。
伪代码
定义一个Integer数组,大小是2的n次方。
然后初始化n=1的时候
for遍历从i=2开始到n
然后for遍历从j=开始位置也就是2的i-1次方,然后这里还需要定义一个k,用来找前面的元素
填充j位置的内容
return Arrays.asList(数组)即可
java代码
class Solution {
public List<Integer> grayCode(int n) {
// 数组长度为2^n
Integer lists[] = new Integer[1 << n];
// 初始化n=1的时候
lists[0] = 0;
lists[1] = 1;
for (int i = 2; i <= n; i++) {
for (int j = 1 << (i - 1), k = 1; j < (1 << i); j++, k++) {
lists[j] = (1 << (i - 1)) + lists[(1 << (i - 1)) - k];
}
}
return Arrays.asList(lists);
}
}
- 总结:题目的关键就是找到这个规律,找到规律之后还是比较简单的。