【LeetCode 89】格雷编码 构建法和自然二进制编码转化法

本文详细介绍了如何解决LeetCode第89题,即格雷编码的构建。通过理解格雷码的特性,我们可以利用递归规则构造代码,或者使用自然二进制码转换的方法。文章提供了两种解题思路的代码实现,并解释了自然二进制码转化为格雷编码的原理。
摘要由CSDN通过智能技术生成

题目:

在这里插入图片描述

思考:

  • 首先,补充一下格雷码的含义:在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码。例如,位数为2格雷码的其中一个序列:00,01,11,10,它们任意两个相邻的数值,只有一个位数不同。
  • 解题思路:如果我们书写三位的格雷码的一个序列:000,001,011,010,110,111,101,100。我们会发现一个奇怪的现象,前面四个数,跟后面四个数,第一位不同,后面刚好后四个数的顺序是前四个数的逆序。通过查阅资料,可知,这是由于格雷码是反射二进制码,我们根据这一特点,利用递归的如下规则来构造:
    • 1位格雷码有两个,n位的格雷码有2*n个
    • (n+1)位格雷码中的前n个码字等于n位格雷码的码字,按顺序书写,加前缀0
    • (n+1)位格雷码中的后n个码字等于n位格雷码的码字,按逆序书写,加前缀1
    • n+1位格雷码的集合 = n位格雷码集合(顺序)加前缀0 + n位格雷码集合(逆序)加前缀1

代码:

	public List<Integer> grayCode(int n) {
        List<Integer> list = new ArrayList<>();
        if (n == 0) {
            list.add(0);
            return list;
        }

		// 这里获得格雷码的二进制码的形式,再将二进制码转为数字
        String[] grayCode = getGrayCode(n);
        for (String s : grayCode
        ) {
            list.add(Integer.parseInt(s, 2));
        }
        return list;
    }

    private String[] getGrayCode(int n) {
        if (n == 1) {
            return new String[]{"0", "1"};
        }

        String[] temp = getGrayCode(n - 1);
        String[] result = new String[temp.length * 2];
        for (int i = 0; i < temp.length; i++) {
     	    // n位格雷码集合(顺序)加前缀0 
            result[i] = "0" + temp[i];
            // n位格雷码集合(逆序)加前缀1
            result[result.length - i - 1] = "1" + temp[i];
        }
        return result;
    }

自然二进制做法:

还有一种做法,是利用自然二进制码,直接转为格雷编码,方法为:将自然二进制码右移一位,与原自然二进制码进行异或操作,即可得到格雷编码。
具体的代码:

	public List<Integer> grayCode1(int n) {
        List<Integer> result = new ArrayList<>();
        for (int i = 0; i < 1 << n; i++) {
            result.add(i ^ i >> 1);
        }
        return result;
    }

自然二进制做法解析:

关于这个规律,为什么能从自然二进制码转为格雷编码,这里按自己的理解解释一下:

  • 对于自然二进制码,进行自增,有两种情况,一种是进位,一种是末位从0变成1。而格雷编码需要对应自然二进制码这两种自增情况时,都只发生一位的修改。
  • 而算法,是将自然二进制码右移一位,与原自然二进制码进行异或操作,对于一个n位的自然二进制数,该变化即保留了最高位不变,有n-1次异或操作,而该格雷码就是最高位加上n-1次异或操作的结果进行拼接。我们现在就需要讨论当二进制编码自增,发生上述两种情况时,格雷编码是否能保证只发生了一位修改
  • 首先考虑,自然二进制码没有发生进位的情况。此时,最后一位,实际上只参与了一组异或计算,即n-1组异或操作,会有一组的值发生了变化,即符合只发生了一位的修改。(下面举例从 0010 -> 0011)
    在这里插入图片描述
  • 第二种情况,即发生进位。比如进位,会导致后面m位都发生变化,即但后面m-1组的异或中,两个元素同时变,因此异或结果没有变。而第m组,只有一个参数发生变化,因此会导致异或计算结果不同。即总体发生一组值的变化,也符合发生了一位的修改。(下面举例从 0011 -> 0100)
    在这里插入图片描述
  • 综上两种情况,可以推断该算法确实可以将自然二进制码转为格雷编码。

相关其他链接

其他 LeetCode 题目
LeetCode Top 100 Liked Questions 题目

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值