2Brute2Best
🔥0

Gray Code

Medium·LeetCode #89Basic Anchor
LeetCode
30-Second Mental ModelBitmask state — Gray code (one bit flips per step)
Complexity:O(N · 2^N)→O(2^N)
Key Insight

The i-th Gray code is i XOR (i >> 1): XOR the number with itself shifted right by one bit. Loop i from 0 to 2^n − 1 and output each code. There is no search and no visited array, because neighbours i and i + 1 always differ in one bit.

Core Validity Invariant

Use code(i) = i XOR (i >> 1) for every i from 0 to 2^n − 1. The codes are all different, and code(i) and code(i + 1) differ in exactly one bit, so the list is valid.

01

Problem

A Gray code is a list of all n-bit numbers in which every two neighbours differ in exactly one bit.

Build one for a given n. The list must hold every number from 0 to 2^n − 1, each one once, and it must start with 0. Any two neighbours in the list must differ in exactly one bit. The last number must also differ from the first (0) in exactly one bit, so the list can loop round.

Return any list that works.

Input

An integer n.

Output

A list of 2^n integers that forms a valid n-bit Gray code. Any valid list is accepted, so the answer is not unique.

Example 1
Input: n = 2
Output: [0, 1, 3, 2]

In binary the list is 00, 01, 11, 10. Each step flips one bit. The last step, 10 → 00, flips one bit too, so the list loops. [0, 2, 3, 1] is also accepted.

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

0 and 1 differ in one bit. The step from 1 back to 0 closes the loop.

Constraints
  • • 1 ≤ n ≤ 16
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    If I list 0, 1, 2, 3 in plain order for n = 2, which neighbouring pair breaks the rule?

  2. 2.

    The list has to hold every number from 0 to 2^n − 1. Does the order matter, or only which numbers appear?

  3. 3.

    From one code, how many codes are exactly one bit away? Can I list the next choices without searching?

  4. 4.

    Is there a rule that gives the i-th code directly, instead of building the list step by step?

  5. 5.

    What must the last code be so that the list loops back to 0?

03

Brute force approach

04

Better approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceFrom 0, flip one bit at a time, never reuse a code, back up when stuckO(N · 2^N)O(2^N)
BetterStart from [0]; each round, append the list in reverse with the new top bit setO(2^N)O(1)
OptimalCode number i is i XOR (i shifted right by one); loop i from 0 to 2^n − 1O(2^N)O(1)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “list all numbers from 0 to 2^n − 1”The set of values is fixed, so only the order is free.
  • “neighbours differ in exactly one bit”Each step is a single bit flip: XOR with one power of two.
  • “the first and last also differ in one bit”The list must loop, so the wrap pair must be one flip apart too.
every n-bit value once+each step flips one bit+the list closes into a loop→Bitmask state — Gray code (one bit flips per step)

Here each state is a bit pattern, and every step flips exactly one bit. This is the anchor of the bitmask sub-pattern: a mask is a state you walk through. What makes this different from Counting Bits or Power of Two is that the order of the values matters, not how many bits they have. The formula works because XOR with a shifted copy turns "flip one bit at a time" into a direct rule.

10

Don't make this mistake

Pattern confusion: counting up in plain binary
✗ for (int i = 0; i < (1 << n); i++) res.push_back(i);
✓ for (int i = 0; i < (1 << n); i++) res.push_back(i ^ (i >> 1));

All the numbers are there, but the order breaks the rule. For n = 2 the plain list is 0, 1, 2, 3. From 1 (01) to 2 (10) flips two bits. The Gray list is 0, 1, 3, 2.

Shifting the wrong way
✗ res.push_back(i ^ (i << 1));
✓ res.push_back(i ^ (i >> 1));

For n = 2 the wrong formula gives 0, 3, 6, 5. The value 6 is outside 0 to 3, so the list is not made of the 2^n codes. The shift has to bring the bit above down, not push bits up.

Reflecting without setting the top bit
✗ codes.push_back(codes[i]);
✓ codes.push_back(codes[i] | top);

For n = 2, starting from [0, 1], the reversed copy without the top bit is [1, 0]. The list becomes [0, 1, 1, 0], which repeats 1. Setting the top bit (value 2) makes the copy [3, 2].

Stopping the DFS at 2^n codes without the loop check
✗ if ((int)path.size() == (1 << n)) return true;
✓ if ((int)path.size() == (1 << n)) return (cur & (cur - 1)) == 0;

For n = 3 the walk 0, 1, 3, 2, 6, 4, 5, 7 uses all 8 codes and flips one bit at each step, but 7 = 111 and 0 differ in three bits. The loop rule is part of the problem, so the last check is needed.

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like Bit Manipulation translate into production architectures and low-level memory mechanics.