leetcode GrayCode
这题一开始想了好多错误的模拟,差点没用上了搜索来做了+_+
后来一查发现有几种方法,顺带给自己也总结一下
1 直接排列法
思路:首先0先进列表, 然后i 从1 - 2^n-1,如果为奇数,就取前一个数的 并且异或1就行了,如果为偶数 取前一个数的右边出现第一个1的位置左移一位(设这个位置为 j ) 并与前一个数异或(1<<j),具体问题像模拟,都有规律可循
public static List<Integer> grayCode(int n) { //直接排列
List<Integer> ls = new ArrayList<Integer>();
ls.add(0);
for(int i = 1; i < 1<<n; i++) {
if(i % 2 == 0) {
int j = 0;
int k = ls.get(ls.size()-1);
while(k % 2 !=1) {
k = k>>1;
j++;
}
j++;
ls.add((1<<j)^(ls.get(ls.size()-1)));
}else {
ls.add((ls.get(ls.size()-1))^1);
}
}
return ls;
}
2镜像复制法
思路:仔细观察就能发现编码是具有对称性的,此处要偷一下wiki上面的一张图
public static List<Integer> grayCode(int n) { //镜像复制法
List<Integer> ls = new ArrayList<Integer>();
ls.add(0);
for(int i = 0; i < n; i++) {
int x = (1<<i);
for(int j = 1; j <= x; j++) {
ls.add(ls.get(x-j)^x);
}
}
return ls;
}
3直接转换
wiki上面有源代码,转化成这题就可以直接跑一遍for循环就行了
public static List<Integer> grayCode(int n){
List<Integer> ls = new ArrayList<Integer>();
for(int i = 0; i < 1<<n; i++) {
ls.add(i^(i>>1)); //重点规律
}
return ls;
}