89. 格雷编码

89. 格雷编码

n 位格雷码序列 是一个由 2^n 个整数组成的序列,其中:每个整数都在范围 [0, 2^n - 1] 内(含 0 和 2^n - 1)

  • 第一个整数是 0;
  • 一个整数在序列中出现 不超过一次;
  • 每对相邻整数的二进制表示 恰好一位不同 ,且第一个最后一个 整数的二进制表示 恰好一位不同;
  • 给你一个整数 n ,返回任一有效的 n 位格雷码序列 ,其中
    1 <= n <= 16。

分析:
若G(n)表示n位格雷编码

  1. n = 0

     G(0):[ 0 ]
    
  2. n = 1

     G(0):[ 0, 0 + 1 ] = [ 0, 1 ] ,倒序为:[ 1, 0 ]
    
  3. n = 2

     G(0):[ 0 , 1 , 1 + 2, 0 + 2] = [ 0, 1, 3, 2 ] 
    
  4. n = 3

     G(0):[ 0, 1, 3, 2 ,2 + 4, 3 + 4, 1 + 4, 0 + 4]  = [ 0, 1, 3, 2, 6, 7, 5, 4 ] 
    

寻找规律:由于格雷码的规则,相邻位必须只有一个二进制位不相同,起始也满足只有一位二进制位不同,所以G(n)为G(n-1)拼接【Gr(n-1)每一位高位补1,即加2^(n-1)】,如下图,其中Gr表示G的转置数列,如:G(1)=[0,1],则Gr[1]=[1,0]
其中:G(0)=[0],G(1)=[0,1]或[1,0]

在这里插入图片描述
方法一:

public List<Integer> grayCode02(int n) {
        List<Integer> grayCode = new ArrayList<>();
        // 从G(0)开始
        grayCode.add(0);
        for (int i = 1; i <= n; i++) {
            // 偏移量 2^n-1
            int offset = 1 << (i - 1);
            for (int j = offset - 1; j >= 0; j--) {
                // 将G(n-1)倒序取值+offset添加至数组后即可得到G(n)
                grayCode.add(grayCode.get(j) + offset);
            }
        }
        return grayCode;
}

方法二:递归的思想,知道递推逻辑,且知道n=0,n=1的结果,递归调用即可得到G(n)

public List<Integer> grayCode(int n) {
     if (n == 0) return Arrays.asList(0);   
     if (n == 1) return Arrays.asList(0,1);
     
     List<Integer> n1 = grayCode(n-1);
     List<Integer> n2 = new ArrayList<>(n1.size() * 2);
     n2.addAll(n1);
     for (int i = n1.size()-1; i>=0; i--) {
         n2.add(n1.get(i) + (1<< (n-1)));
     }
     return n2;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值