【Leetcode】【20220108】【格雷编码】格雷编码的对称生成

题目来源:https://leetcode-cn.com/problems/gray-code/
思路原著:https://leetcode-cn.com/u/zzpig/
格雷编码:https://baike.baidu.com/item/%E6%A0%BC%E9%9B%B7%E7%A0%81/6510858

题目

n位格雷码序列是一个由2n个整数组成的序列,其中:

  1. 每个整数都在范围[0,2n-1]内(含0和2n-1)
  2. 第一个整数是0
  3. 一个整数在序列中出现不超过一次
  4. 每对相邻整数的二进制表示恰好一位不同,且
  5. 第一个和最后一个整数的二进制表示恰好一位不同

给你一个整数n,返回任一有效的n位格雷码序列。

示例

输入: n=2

输出:[0,1,3,2]

解题思路

在这里插入图片描述

首先是发现规律:剔除掉首位二进制码,格雷编码的前半段与后半段完全相反。而首位的区别也仅仅是前半段为0,后半段为1。于是开始分析思路:

如图,首先在List中初始化首位为0,则其二进制表示方式为 0000

此时List中的值为:0000

定义一个head,用来存放待相加的值,定为1,因为接下来要0000改变成0001

在list中添加head与list中所有值逆序相加的结果,譬如现在:List中只有0000,List逆序后也是0000,将head相加,值为0001,将0001添加到list中。

此时List中的值为:0000,0001

然后让head位运算左移一位,从0001变成0010

在list中添加head与list中所有值逆序相加的结果,譬如现在:List中有00000001,List逆序后是00010000,将head相加,值分别为0011,0010,将这两个值add到List中。

此时List中的值为:0000,0001,0011,0010

然后让head位运算左移一位,从0010变成0100

在list中添加head与list中所有值逆序相加的结果,譬如现在:List中有0000,0001,0011,0010,List逆序后是0010,0011,0001,0000,将head相加,值分别为0110,0111,0101,0100,将这四个值add到List中。

此时List中的值为:0000,0001,0011,0010,0110,0111,0101,0100

然后让head位运算左移一位,从0100变成1000

重复上述操作,得到相加后的值:1100,1101,1111,1110,1010,1011,1001,1000,将该8个值add到List中。

此时便得到了n=4时的grayCode,返回这个List即可。

代码实现

    public static List<Integer> grayCode(int n) {
        //创建List用于存储结果
        List<Integer> res = new ArrayList<>();
        //先向List中添加0
        res.add(0);
        //如果n=0,那么此时只含有1个0的res就是所需格雷编码,无需进行任何操作
        if (n != 0)
            //n=4,表示格雷码为4位,head从二进制0001开始 移动到二进制1000一共需要移动3次
            for (int i = 0, head = 1; i < n; i++) {
                //将head与当前List中所有的值逆序相加并add到List中
                for (int j = res.size() - 1; j >= 0; j--)
                    res.add(head + res.get(j));
                //逆序相加完毕,head位运算左移1位
                head = head << 1;
            }
        //返回计算后的结果
        return res;
    }

执行用时:7 ms, 在所有 Java 提交中击败了66.30%的用户
内存消耗:45.8 MB, 在所有 Java 提交中击败了21.12%的用户

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值