LeetCode Solutions
753. Cracking the Safe
Time: $O(k^{k^n}) \to O(k^n)$ Space: $O(k^n)$
class Solution {
public:
string crackSafe(int n, int k) {
string ans(n, '0');
dfs(pow(k, n), n, k, {ans}, ans);
return ans;
}
private:
bool dfs(int passwordSize, int n, int k, unordered_set<string>&& seen,
string& path) {
if (seen.size() == passwordSize)
return true;
string prefix = path.substr(path.length() - n + 1);
for (char c = '0'; c < '0' + k; ++c) {
prefix.push_back(c);
if (!seen.count(prefix)) {
seen.insert(prefix);
path.push_back(c);
if (dfs(passwordSize, n, k, move(seen), path))
return true;
path.pop_back();
seen.erase(prefix);
}
prefix.pop_back();
}
return false;
}
};
class Solution {
public String crackSafe(int n, int k) {
final String allZeros = "0".repeat(n);
StringBuilder sb = new StringBuilder(allZeros);
dfs((int) Math.pow(k, n), n, k, new HashSet<>(Arrays.asList(allZeros)), sb);
return sb.toString();
}
private boolean dfs(int passwordSize, int n, int k, Set<String> seen, StringBuilder path) {
if (seen.size() == passwordSize)
return true;
StringBuilder prefix = new StringBuilder(path.substring(path.length() - n + 1));
for (char c = '0'; c < '0' + k; ++c) {
prefix.append(c);
final String prefixStr = prefix.toString();
if (!seen.contains(prefixStr)) {
seen.add(prefixStr);
path.append(c);
if (dfs(passwordSize, n, k, seen, path))
return true;
path.deleteCharAt(path.length() - 1);
seen.remove(prefixStr);
}
prefix.deleteCharAt(prefix.length() - 1);
}
return false;
}
}
class Solution:
def crackSafe(self, n: int, k: int) -> str:
passwordSize = k**n
path = '0' * n
seen = set()
seen.add(path)
def dfs(path: str) -> str:
if len(seen) == passwordSize:
return path
for c in map(str, range(k)):
node = path[-n + 1:] + c if n > 1 else c
if node not in seen:
seen.add(node)
res = dfs(path + c)
if res:
return res
seen.remove(node)
return dfs(path)