89.格雷编码

·题目描述

89. 格雷编码

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

  • 每个整数都在范围 [0, 2n - 1] 内(含 0 和 2n - 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));
    }
}
相关推荐
非优秀程序员6 小时前
第05章 播放器大战,暴风、快播与那一夜|《互联网产品恩仇录》
算法
非优秀程序员6 小时前
第04章 邮箱大战,163 与 QQ 的暗战|《互联网产品恩仇录》
java·vue.js·架构
知已难寻7 小时前
Docker 入门:容器技术与 Docker 基础
java·运维·服务器·docker·云原生·容器
文丑颜不良啊9 小时前
LeetCode2481~2500题目解析
java·leetcode
Flynn Liang10 小时前
同一需求三套写法:用 Spring AI、LangChain4j、AgentScope Java 各实现一个带工具调用的 RAG 助手(实战对比)
java·人工智能·大模型·架构设计·spring ai·langchain4j·agentscope
聪明的笨猪猪11 小时前
实际工程问题:AI 生成 Spring Cache(@Cacheable / @CachePut / @CacheEvict)缓存注解踩坑
java·经验分享·面试·ai编程
愿有所息11 小时前
记一次 ARM64 + JDK8 上 fastjson2 的诡异数据错乱
java
秋饼11 小时前
MCP 2026-07-28 无状态协议大改版:Spring AI 2.1 多轮往返请求与网关路由落地
java·ai·技术分享·后端开发
SL_staff12 小时前
JVS-BI 实战:业务人员如何用零代码 ELT + 可视化配置构建实时经营分析闭环
java·spring·全栈