GoCalf Calf 的自留地 · 昙花一现

89. Gray Code

Problem

An n-bit gray code sequence is a sequence of 2ⁿ integers where:

  • Every integer is in the inclusive range [0, 2ⁿ - 1],
  • The first integer is 0,
  • An integer appears no more than once in the sequence,
  • The binary representation of every pair of adjacent integers differs by exactly one bit, and
  • The binary representation of the first and last integers differs by exactly one bit.

Given an integer n, return any valid n-bit gray code sequence.

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

Example 1:

Input: n = 2
Output: [0,1,3,2]
Explanation:
The binary representation of [0,1,3,2] is [00,01,11,10].

  • 00 and 01 differ by one bit
  • 01 and 11 differ by one bit
  • 11 and 10 differ by one bit
  • 10 and 00 differ by one bit

[0,2,3,1] is also a valid gray code sequence, whose binary representation is [00,10,11,01].

  • 00 and 10 differ by one bit
  • 10 and 11 differ by one bit
  • 11 and 01 differ by one bit
  • 01 and 00 differ by one bit

Example 2:

Input: n = 1
Output: [0,1]

Constraints:

  • 1 <= n <= 16

Test Cases

python
class Solution:
    def grayCode(self, n: int) -> List[int]:
solution_test.py下载完整源码
py
import pytest

from solution import Solution


# 191-number-of-1-bits#Another-Way
def hamming_weight(n: int) -> int:
    cnt = 0
    while n > 0:
        cnt += 1
        n &= n - 1

    return cnt


def validate_gray_code(nums: list[int]) -> None:
    n = len(nums)
    assert sorted(nums) == list(range(n))
    assert nums[0] == 0
    for i in range(len(nums)):
        assert hamming_weight(nums[i-1] ^ nums[i]) == 1


@pytest.mark.parametrize('n, expected', [
    (2, [0,1,3,2]),
    (1, [0,1]),
])
@pytest.mark.parametrize('sol', [Solution()])
def test_solution(sol, n, expected):
    result = sol.grayCode(n)
    if result != expected:
        assert len(result) == 2 ** n
        validate_gray_code(result)

Thoughts

格雷编码序列,两个连续的数值仅有一个(二进制)位数的差异。

如果已经得到了 n - 1 的格雷编码序列 [g₁, g₂, ..., gₘ](m = 2ⁿ⁻¹),其中每个数字的第 n 个二进制位都一定是 0。可以把每个数字的第 n 个二进制位都置为 1,得到新的序列 [g'₁, g'₂, ..., g'ₘ],显然新序列中任意两个连续的数值都仅有一个位数的差异。把第二个序列逆序拼接到第一序列后边,得到 [g₁, g₂, ..., gₘ, g'ₘ, g'ₘ₋₁, ..., g'₂, g'₁],这就是 n 的格雷编码序列。

初始时 n = 0 的格雷编码序列就是 [0]。

Code

py
class Solution:
    def grayCode(self, n: int) -> list[int]:
        result = [0]
        for i in range(n):
            diff = 1 << i
            result.extend(x + diff for x in reversed(result))
        return result

评论需要 JavaScript。