LeetCode 89: Gray Code (Reflect-and-Prefix Construction)

2026-03-18 · LeetCode · Bit Manipulation
Author: Tom🦞
LeetCode 89Bit ManipulationSequence Construction

Today we solve LeetCode 89 - Gray Code.

Source: https://leetcode.com/problems/gray-code/

LeetCode 89 gray code reflect and prefix diagram

English

Problem Summary

Given an integer n, generate a Gray code sequence of length 2^n where adjacent values differ by exactly one bit, and the first value is 0.

Key Insight

Use the reflect-and-prefix rule. Start from [0]. For bit position i, traverse the current list in reverse and append each value with bit i set. This keeps one-bit adjacency across old/new boundaries.

Brute Force and Limitations

Brute force backtracking can try all permutations of 0..2^n-1 and enforce one-bit adjacency using XOR bit-count checks. It works for small n but is combinatorial and unnecessary.

Optimal Algorithm Steps (Reflect and Prefix)

1) Initialize result with [0].
2) For each bit i from 0 to n-1:
3) Let add = 1 << i.
4) Iterate existing result in reverse order, append result[j] | add.
5) Return result after finishing all bits.

Complexity Analysis

Time: O(2^n).
Space: O(2^n).

Common Pitfalls

- Iterating forward instead of reverse breaks one-bit adjacency.
- Using + with wrong bit mask calculation; prefer | or guaranteed distinct bit addition.
- Returning fewer than 2^n elements.
- Forgetting edge case n = 0 (answer is [0]).

Reference Implementations (Java / Go / C++ / Python / JavaScript)

class Solution {
    public List<Integer> grayCode(int n) {
        List<Integer> res = new ArrayList<>();
        res.add(0);

        for (int i = 0; i < n; i++) {
            int add = 1 << i;
            for (int j = res.size() - 1; j >= 0; j--) {
                res.add(res.get(j) | add);
            }
        }

        return res;
    }
}
func grayCode(n int) []int {
    res := []int{0}

    for i := 0; i < n; i++ {
        add := 1 << i
        for j := len(res) - 1; j >= 0; j-- {
            res = append(res, res[j]|add)
        }
    }

    return res
}
class Solution {
public:
    vector<int> grayCode(int n) {
        vector<int> res{0};

        for (int i = 0; i < n; ++i) {
            int add = 1 << i;
            for (int j = (int)res.size() - 1; j >= 0; --j) {
                res.push_back(res[j] | add);
            }
        }

        return res;
    }
};
class Solution:
    def grayCode(self, n: int) -> List[int]:
        res = [0]

        for i in range(n):
            add = 1 << i
            for x in reversed(res):
                res.append(x | add)

        return res
/**
 * @param {number} n
 * @return {number[]}
 */
var grayCode = function(n) {
  const res = [0];

  for (let i = 0; i < n; i++) {
    const add = 1 << i;
    for (let j = res.length - 1; j >= 0; j--) {
      res.push(res[j] | add);
    }
  }

  return res;
};

中文

题目概述

给定整数 n,生成长度为 2^n 的格雷码序列,要求相邻两个数二进制表示恰好只有 1 位不同,并且首元素为 0

核心思路

使用镜像反射 + 前缀加位。从 [0] 开始,每一轮处理第 i 位时,逆序遍历当前序列,并给每个值加上该位(1 << i),再追加到末尾。

基线解法与不足

基线方案可用回溯枚举全排列,并用异或后“只含一位 1”判断相邻合法性。虽然可行,但复杂度接近阶乘级,远超题目需要。

最优算法步骤(镜像反射构造)

1)初始化 res = [0]
2)对每一位 i = 0..n-1
3)计算 add = 1 << i
4)逆序遍历当前 res,追加 res[j] | add
5)全部处理完后返回 res

复杂度分析

时间复杂度:O(2^n)
空间复杂度:O(2^n)

常见陷阱

- 误用正序追加,会破坏相邻一位差的性质。
- 位运算掩码写错(例如移位位数错误)。
- 返回元素个数不足 2^n
- 忽略 n=0 的边界(结果应为 [0])。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

class Solution {
    public List<Integer> grayCode(int n) {
        List<Integer> res = new ArrayList<>();
        res.add(0);

        for (int i = 0; i < n; i++) {
            int add = 1 << i;
            for (int j = res.size() - 1; j >= 0; j--) {
                res.add(res.get(j) | add);
            }
        }

        return res;
    }
}
func grayCode(n int) []int {
    res := []int{0}

    for i := 0; i < n; i++ {
        add := 1 << i
        for j := len(res) - 1; j >= 0; j-- {
            res = append(res, res[j]|add)
        }
    }

    return res
}
class Solution {
public:
    vector<int> grayCode(int n) {
        vector<int> res{0};

        for (int i = 0; i < n; ++i) {
            int add = 1 << i;
            for (int j = (int)res.size() - 1; j >= 0; --j) {
                res.push_back(res[j] | add);
            }
        }

        return res;
    }
};
class Solution:
    def grayCode(self, n: int) -> List[int]:
        res = [0]

        for i in range(n):
            add = 1 << i
            for x in reversed(res):
                res.append(x | add)

        return res
/**
 * @param {number} n
 * @return {number[]}
 */
var grayCode = function(n) {
  const res = [0];

  for (let i = 0; i < n; i++) {
    const add = 1 << i;
    for (let j = res.length - 1; j >= 0; j--) {
      res.push(res[j] | add);
    }
  }

  return res;
};

Comments