Grey Code
An n-bit gray code sequence is a sequence of 2^n integers where:
- Every integer is in the inclusive range
[0, 2^n - 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.
Example 1:
Input: n = 2
Output: [0,1,3,2]
Explanation:
The binary representation of [0,1,3,2] is [00,01,11,10].
00and01differ by one bit01and11differ by one bit11and10differ by one bit10and00differ by one bit
[0,2,3,1] is also a valid gray code sequence, whose binary representation is [00,10,11,01].
00and10differ by one bit10and11differ by one bit11and01differ by one bit01and00differ by one bit
Example 2:
Input: n = 1
Output: [0,1]
Constraints:
1 <= n <= 16
Solution
In this question, we are dealing with binary representation of integers, we will be using bit manipulation. To learn more, checkout Bitmask Intro.
The two important operations we will use are the shift operator (<<) and the XOR (exclusive or) operator (^).
1 << i: will shift1byibits to the left, the new binary number will haveizeros after a1.code ^ (1 << i): flips theith bit (from the right) incode's binary representation. By the property of XOR that0^1 = 1and1^1 = 0.
Now, we can use these two operations to find the candidates for the next code. And since we are only looking for one solution, we can use the aggregation template to return earlier. We will apply the backtracking2 template and fill in the logic.
is_leaf:start_index == 2**n, we have used all integersget_edges:new_code = code ^ (1 << i)where0 <= i < n, thisnew_codehas one flipped bit on thei-th bit, it can potentially be the next codeis_valid:new_codeis valid when we have not used it (not in visited)
Implementation
def grayCode(self, n: int) -> List[int]:
length = 1 << n # same as 2**n
visited = [False] * length
def dfs(start_index, code):
if start_index == length:
return True
for i in range(n):
new_code = code ^ (1 << i)
print(new_code)
if not visited[new_code]:
path.append(new_code)
visited[new_code] = True
if dfs(start_index+1, new_code): return True
visited[new_code] = False
path.pop()
return False
path = [0]
visited[0] = True
dfs(1, 0)
return path

Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorIs the following code DFS or BFS?
void search(Node root) { if (!root) return; visit(root); root.visited = true; for (Node node in root.adjacent) { if (!node.visited) { search(node); } } }
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion If you prefer videos here's a video that explains recursion in a fun and easy way Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask him
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!