AlgoMaster Logo

Cracking the Safe

Last Updated: March 28, 2026

hard
4 min read

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.

Think about it this way: with n = 2 and k = 2, we have four possible passwords: "00", "01", "10", "11". We could naively concatenate them all to get "00011011" (length 8), but that is wasteful. Notice that consecutive passwords can overlap. The end of one password can serve as the beginning of the next. "01100" achieves the same coverage in just 5 characters by maximizing these overlaps.

The key observation is that this problem maps directly onto finding an Eulerian path in a specific graph. Each password of length n becomes an edge, and each prefix/suffix of length n-1 becomes a node. Finding a path that traverses every edge exactly once gives us 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.
  • The small constraints mean both backtracking and Hierholzer's algorithm are viable. The elegant solution models this as an Eulerian path problem.

Approach 1: DFS Backtracking

Intuition

The most direct way to think about this: we need to build a string that contains every possible n-digit combination as a substring. Start with a string of n zeroes (that is our first password). Then repeatedly try to extend by one character such that the last n characters form a new, previously unseen password.

If we hit a dead end where all extensions lead to passwords we have already seen, we backtrack. The backtracking ensures we find a valid path through all k^n passwords. We are essentially doing a DFS on the de Bruijn graph, but without explicitly constructing the graph.

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

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

Code

The backtracking approach works but may explore dead-end branches. Since the de Bruijn graph is guaranteed to have an Eulerian circuit, can we use Hierholzer's algorithm to find the path directly without any backtracking?

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 is Eulerian. Hierholzer's algorithm finds this circuit by doing a DFS with post-order edge collection: start at any node, follow edges greedily, and when stuck, append the digit to the result and backtrack through the recursion.

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, with k outgoing edges.
  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.
  5. After exploring all edges from a node, append the current digit to the result (post-order).
  6. Append the starting node to the result at the end.

Example Walkthrough

1Start DFS at node "0". Try edge "00" → go to node "0"
1/8

Code