89.格雷编码

·题目描述

89. 格雷编码

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

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

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

示例 1:

复制代码
输入:n = 2
输出:[0,1,3,2]
解释:
[0,1,3,2] 的二进制表示是 [00,01,11,10] 。
- 00 和 01 有一位不同
- 01 和 11 有一位不同
- 11 和 10 有一位不同
- 10 和 00 有一位不同
[0,2,3,1] 也是一个有效的格雷码序列,其二进制表示是 [00,10,11,01] 。
- 00 和 10 有一位不同
- 10 和 11 有一位不同
- 11 和 01 有一位不同
- 01 和 00 有一位不同

示例 2:

复制代码
输入:n = 1
输出:[0,1]

·格雷编码的规律

格雷编码是n= 0 也就是编码数组nums = 【0】开始往上递增的。递增的规律有两个:

1.保持nums数组中前元素不变,在nums后端不断添加新元素。新元素的构成是在原始数组上逆序遍历,再在该元素的最高位添加一个1 ,在二进制中表述为

复制代码
(ground.get(i) | size)
size = nums.size()

表示对nums列表中的第 i 个元素执行按位或操作,并且按位或操作的右操作数是 size

复制代码
假设 nums 列表当前包含 [0, 1],并且 size 是 4。

对于 nums.get(0) = 0:

nums.get(0) | size 将会生成一个新的 Gray 码。
nums.get(0) 的二进制表示是 0000,size 的二进制表示是 0100。
将它们进行按位或运算:0000 | 0100,得到结果 0100,即 4。
对于 nums.get(1) = 1:

nums.get(1) | size 将会生成另一个新的 Gray 码。
nums.get(1) 的二进制表示是 0001,size 的二进制表示是 0100。
将它们进行按位或运算:0001 | 0100,得到结果 0101,即 5。

2.原始的nums元素全部左移并且后端添上0,在十进制中表示为×2的操作;然后采用逆序,nums的元素左移并且后端添加1,添加到nums后端。

例如

n = 1 时候 , nums = 0 , 1

复制代码
将0->00, 1 -> 10,并且逆序遍历1->11,0 ->01

所以n = 2 的时候, nums =00, 01, 11, 10

同理可得 ,n = 3 的时候, nums = 000,010,110,100 , 101,111,011,001

java 复制代码
import java.util.ArrayList;
import java.util.List;

class Solution {
    List<Integer> ground = new ArrayList<>();

    public List<Integer> grayCode(int n) {
        ground.add(0);
        backtrack(n);
        return ground;
    }
    public void backtrack( int n) {
        int size = ground.size();
        if (size == (int) Math.pow(2,n)) return;
        
        //构建方法1
        for(int i = size - 1; i >= 0; i --){
            int num = (ground.get(i) | size)  ;
            ground.add(num);
        }
        backtrack(n);
        
        //构建方法2
        for(int i = size - 1; i >= 0; i --){
            int num = (ground.get(i) << 1) | 1 ;
            ground.add(num);
        }
        for(int i = 0; i < size ; i ++){
            ground.set(i , ground.get(i) * 2);
        }
        backtrack(n);
    }
}

public class Main {
    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println(solution.grayCode(3));
    }
}
相关推荐
萧瑟余晖几秒前
Java深入解析篇六十一之编译器API(javax.tools)详解
java·开发语言
HugoStudio_SWAN12 分钟前
洛谷 P10719 \[GESP202406 五级] 黑白格——暴力美学与图像处理的最小外接矩形
c++·图像处理·人工智能·学习·程序人生·算法·目标跟踪
那年窗外下的雪.19 分钟前
AIDC 学习日志|第 20 天|多归属业务验收与哈希不均定位
学习·算法·哈希算法
码云数智-园园25 分钟前
C++ STL 容器怎么选?vector、list、map、unordered_map 优缺点对比
java·开发语言
YSL07012428 分钟前
时间复杂度和空间复杂度
数据结构
en.en..32 分钟前
竖线 |:管道、按位或、掩码组合
java·开发语言
洋不写bug40 分钟前
链表面试笔试经典题目详细解析,题目多解法,复杂度分析
数据结构·链表·面试
程序猿乐锅1 小时前
【计算机组成原理 | 第六章】中央处理器 CPU
java·开发语言
大模型丫丫1 小时前
如何提升单体 Spring Boot 应用的并发数?
java·spring boot·后端
Terra.K1 小时前
ThreadLocal解决一个线程里面跨层传递问题
java·开发语言·后端