There is a safe protected by a password. The password is a sequence of n
digits where each digit can be in the range [0, k - 1]
.
The safe has a peculiar way of checking the password. When you enter in a sequence, it checks the most recent n
digits that were entered each time you type a digit.
"345"
and you enter in "012345"
:
0
, the most recent 3
digits is "0"
, which is incorrect.1
, the most recent 3
digits is "01"
, which is incorrect.2
, the most recent 3
digits is "012"
, which is incorrect.3
, the most recent 3
digits is "123"
, which is incorrect.4
, the most recent 3
digits is "234"
, which is incorrect.5
, the most recent 3
digits is "345"
, which is correct and the safe unlocks.Return any string of minimum length that will unlock the safe at some point of entering it.
Example 1:
Input: n = 1, k = 2 Output: "10" Explanation: The password is a single digit, so enter each digit. "01" would also unlock the safe.
Example 2:
Input: n = 2, k = 2 Output: "01100" Explanation: For each possible password: - "00" is typed in starting from the 4th digit. - "01" is typed in starting from the 1st digit. - "10" is typed in starting from the 3rd digit. - "11" is typed in starting from the 2nd digit. Thus "01100" will unlock the safe. "10011", and "11001" would also unlock the safe.
Constraints:
1 <= n <= 4
1 <= k <= 10
1 <= kn <= 4096
This problem can be elegantly solved using the concept of an Eulerian circuit in graph theory. Let's break down the solution:
1. Graph Representation:
The problem can be modeled as a directed graph where:
Nodes: Each node represents a unique sequence of n-1
digits. For example, if n=3
and k=2
, the nodes would be "00", "01", "10", "11".
Edges: A directed edge exists from node u
to node v
if appending a digit x
(0 ≤ x < k) to u
results in a sequence where the last n-1
digits form v
. The edge is labeled with the digit x
.
2. Eulerian Circuit:
An Eulerian circuit is a path in a graph that visits every edge exactly once and ends at the starting node. Our constructed graph has the property that:
k
incoming and k
outgoing edges). This is a necessary and sufficient condition for the existence of an Eulerian circuit in a directed graph.3. Algorithm:
The algorithm uses Depth-First Search (DFS) to find an Eulerian circuit:
n-1
times).k-1
).x
leads to a new, unvisited edge, add the edge to the path (visit it), update the current node, and recursively call DFS from the new node.n-1
zeros to the end to ensure the final sequence unlocks the safe.Time Complexity: O(kn)
The graph has k(n-1) nodes and k * k(n-1) = kn edges. The DFS traversal visits each edge exactly once.
Space Complexity: O(kn)
The space complexity is dominated by the vis
set (to track visited edges) which can store up to kn elements in the worst case. The recursion stack during DFS can also have depth up to kn.
Code Examples (Python):
class Solution:
def crackSafe(self, n: int, k: int) -> str:
mod = 10**(n-1)
visited = set()
ans = []
def dfs(u):
for i in range(k):
v = (u * 10 + i) % mod
if (u, i) not in visited:
visited.add((u, i))
dfs(v)
ans.append(str(i))
dfs(0)
ans.extend(['0'] * (n - 1)) # Add trailing zeros
return ''.join(ans)
Other languages (Java, C++, Go, Typescript) follow a similar structure, with minor variations in syntax and data structures used for the graph representation and visited edges tracking. The core algorithm remains the same — DFS-based Eulerian circuit construction.