LeetCode 89 gray code 格雷编码

版权声明:转载请注明原址,有错误欢迎指出 https://blog.csdn.net/iwts_24/article/details/83586522

题目链接

https://leetcode-cn.com/problems/gray-code/

题意

        有可能是因为机翻,题目描述不太清楚。学过数字电路的应该能秒懂了。实际上就是给出一个n,那么有[0,2^n-1]总共2^n个数。现在对这些数进行排序放在List里,要求按照格雷编码的形式。格雷编码是相邻两个数的二进制只有一位是不同的,例如1、3可以相邻,其二进制为01和11,只有1位不同。而题目要求所有的相邻的两个数之间都是只有一位不同。

题解

        据说Google面试题,挺考思维的。刚开始很懵,不知道从哪里开始下手好,冥冥之中感觉是要找规律,毕竟是按照格雷码来,每次换一位的话,是否能够按照一定的顺序轮着换,这样既能保证是格雷编码,同时又不会把中间的数给漏掉。并且二进制如果只对一位进行反转,那么直接异或运算就行了,可实施程度也比较高。然后就有下面的图:

主要是中间红框内容。是0-15的二进制,而且相邻都是差一位。弧度扩的1、2、3等数字代表前一个数与后一个数相比,第几位翻转了。这是在研究n = 4的时候发现的。那么其翻转位的顺序为:

n = 2       1 2 1

n = 3       1 2 1 3 1 2 1

可以发现,位数“很怂”,一定要保证每次高位翻转一次就要到最低位再翻转一次。所以试着写出来了上图。那么:

n = 4       1 2 1 3 1 2 1 4 1 2 1 3 1 2 1

同时对比这3种情况,发现翻转是以回文数的形式进行的,以n为轴,以n-1的情况为两侧数据。那么对于i,构造出来一侧的情况,加上i+1,在将一侧给复制过去,就得到了i+1的翻转情况。这样,在一次for循环中就可以得到n的翻转情况。有代码:

public static void init(int n){
    N = n;
    grayconfig = new ArrayList<Integer>();
    grayconfig.add(2);
    for(int i = 3;i <= N;i++){
        ArrayList<Integer> temp = (ArrayList<Integer>) grayconfig.clone();
        grayconfig.add(i);
        for(int j = 0;j < temp.size();j++){
            grayconfig.add(temp.get(j));
        }
    }
}

这里我简写了,对于0到1的转换就没写进去,所以第一位一定是2,然后从第二位开始计算就可以了。因为我们要构造回文,所以计算出一侧以后,利用clone,直接clone到后面。这样也不用考虑范围问题。 

        接下来就好办了,既然知道了如何翻转,那么对于数组中i位应该放谁,就把i-1位进行对应的翻转后存进数组即可。翻转这里利用异或。例如我们对于二进制110110的第二位翻转想得到110100,那么我们可以:

110110 xor 000010 = 110100

而这个异或的值也非常简单,1后面n个0,明显是2^n,也就是说,可以得到方法:

public static int flip(int number,int index){
    int bit = (int) Math.pow(2,index-1);
    return number^bit;
}

就能翻转了。按照上面写的,轮次翻转就能得到最终答案。

        但是这样就忽略了特殊情况:n = 0和n = 1。n = 0的时候应该有2^0 = 1位,因为第一位要是0开头,所以就是0。n = 1的时候是2^1 = 2,那么0开头以后,下面是1就完事了,这两个判定以后,其他就正常了。

Java 代码

import java.util.List;

class Solution {
    public static int N;
    public static ArrayList<Integer> grayconfig;
    
    public static void init(int n){
        N = n;
        grayconfig = new ArrayList<Integer>();
        grayconfig.add(2);
        for(int i = 3;i <= N;i++){
            ArrayList<Integer> temp = (ArrayList<Integer>) grayconfig.clone();
            grayconfig.add(i);
            for(int j = 0;j < temp.size();j++){
                grayconfig.add(temp.get(j));
            }
        }
    }
    
    public static int flip(int number,int index){
        int bit = (int) Math.pow(2,index-1);
        return number^bit;
    }
    
    public List<Integer> grayCode(int n) {
        List<Integer> ans = new ArrayList<Integer>();
        ans.add(0);
        if(n == 0) return ans;
        if(n == 1){
            ans.add(1);
            return ans;
        }
        init(n);
        int number = 0;
        number = flip(number,1);
        ans.add(number);
        for(int i = 0;i < grayconfig.size();i++){
            number = flip(number,grayconfig.get(i));
            ans.add(number);
            number = flip(number,1);
            ans.add(number);
        }
        return ans;
    }
}

猜你喜欢

转载自blog.csdn.net/iwts_24/article/details/83586522