AlgoMaster Logo

Cracking the Safe

hardFrequency6 min readUpdated June 23, 2026

Understanding the Problem

This problem is asking us to construct the shortest possible string that contains every combination of n digits (drawn from 0 to k-1) as a contiguous substring. This is a classic problem in combinatorics known as a de Bruijn sequence.

With n = 2 and k = 2, there are four possible passwords: "00", "01", "10", "11". Concatenating them all gives "00011011" (length 8), but consecutive passwords can overlap: the end of one password can serve as the beginning of the next. "01100" achieves the same coverage in 5 characters by maximizing these overlaps.

This problem maps onto finding an Eulerian path in a graph where each password of length n is an edge and each string of length n-1 is a node. A path that traverses every edge exactly once spells out the shortest string containing all passwords.

Key Constraints:

  • 1 <= n <= 4 and 1 <= k <= 10 → The total number of passwords is k^n, which is at most 4096. This is a small search space, so even approaches with higher constant factors will pass.
  • 1 <= k^n <= 4096 → The output string length is k^n + n - 1, which is at most 4099 characters. Any reasonable algorithm will work within time limits.
  • Both backtracking and Hierholzer's algorithm fit comfortably within these limits, so the choice between them is about cleanliness, not performance.

Approach 1: DFS Backtracking

Intuition

Build the string greedily. Start with a string of n zeroes (the first password), then repeatedly extend it by one character so that the last n characters form a new, previously unseen password. This is a DFS on the de Bruijn graph without constructing the graph explicitly: the current node is the last n-1 characters, and each appended digit follows one edge.

If every extension leads to a password we have already seen, we backtrack: remove the character, unmark the password, and try a different digit one level up. The digit order in the code is deliberate. Starting from all zeroes and always trying the largest available digit first produces a complete de Bruijn sequence without ever reaching a dead end (a classical result due to Martin), so the backtracking branch is a safety net that never fires.

Algorithm

  1. Start with a string of n zeroes. Mark this as a visited password.
  2. Use DFS: at each step, take the last n-1 characters of the current string as the current suffix.
  3. Try appending each digit from k-1 down to 0 to form a candidate password of length n.
  4. If the candidate has not been visited, mark it visited, append the digit to the result, and recurse.
  5. If the recursion reaches k^n visited passwords, we have found our answer.
  6. If a branch fails, unmark the candidate and remove the appended digit (backtrack).

Example Walkthrough

Trace n = 2, k = 2. The string starts as "00" and digits are tried from k-1 down to 0:

1Start: result = "00", visited = {"00"}
0
0
1
0
1/5

Code

Approach 1 avoids dead ends only because of its greedy digit order. The next approach uses the graph structure directly: the de Bruijn graph always contains an Eulerian circuit, and Hierholzer's algorithm constructs one with no backtracking machinery at all.

Approach 2: Hierholzer's Algorithm (Eulerian Path)

Intuition

Model the problem as a directed graph where each node is a string of length n-1, and each edge is a password of length n connecting its prefix to its suffix. Each node has exactly k outgoing and k incoming edges, so the graph contains an Eulerian circuit. Hierholzer's algorithm finds this circuit with a DFS that collects edges in post-order: from each node, follow every unused edge, and append an edge's digit to the result only after the recursive call for that edge has fully finished. Appending the start node at the end completes the sequence.

Algorithm

  1. Handle the special case n = 1 by returning digits 0 through k-1 concatenated.
  2. Build the de Bruijn graph implicitly: each node is a string of length n-1. Appending a digit d to node u forms the edge u + d, whose destination node is the last n-1 characters of the edge.
  3. Start DFS from the node consisting of n-1 zeroes.
  4. At each node, try each digit 0 through k-1. If the resulting edge has not been visited, mark it and recurse into its destination node.
  5. When the recursive call for an edge returns, append that edge's digit to the result (post-order).
  6. After the DFS finishes, append the starting node to the result.

Example Walkthrough

Trace n = 2, k = 2. The nodes are the single digits "0" and "1", and the four edges are the passwords "00", "01", "10", "11":

1Start DFS at node "0" (the start node). result = ""
1/10

Code