有一个需要密码才能打开的保险箱。密码是 n
位数, 密码的每一位都是范围 [0, k - 1]
中的一个数字。
保险箱有一种特殊的密码校验方法,你可以随意输入密码序列,保险箱会自动记住 最后 n
位输入 ,如果匹配,则能够打开保险箱。
- 例如,正确的密码是
"345"
,并且你输入的是"012345"
:<ul> <li>输入 <code>0</code> 之后,最后 <code>3</code> 位输入是 <code>"0"</code> ,不正确。</li> <li>输入 <code>1</code> 之后,最后 <code>3</code> 位输入是 <code>"01"</code> ,不正确。</li> <li>输入 <code>2</code> 之后,最后 <code>3</code> 位输入是 <code>"012"</code> ,不正确。</li> <li>输入 <code>3</code> 之后,最后 <code>3</code> 位输入是 <code>"123"</code> ,不正确。</li> <li>输入 <code>4</code> 之后,最后 <code>3</code> 位输入是 <code>"234"</code> ,不正确。</li> <li>输入 <code>5</code> 之后,最后 <code>3</code> 位输入是 <code>"345"</code> ,正确,打开保险箱。</li> </ul> </li>
在只知道密码位数 n
和范围边界 k
的前提下,请你找出并返回确保在输入的 某个时刻 能够打开保险箱的任一 最短 密码序列 。
示例 1:
输入:n = 1, k = 2 输出:"10" 解释:密码只有 1 位,所以输入每一位就可以。"01" 也能够确保打开保险箱。
示例 2:
输入:n = 2, k = 2 输出:"01100" 解释:对于每种可能的密码: - "00" 从第 4 位开始输入。 - "01" 从第 1 位开始输入。 - "10" 从第 3 位开始输入。 - "11" 从第 2 位开始输入。 因此 "01100" 可以确保打开保险箱。"01100"、"10011" 和 "11001" 也可以确保打开保险箱。
提示:
1 <= n <= 4
1 <= k <= 10
1 <= kn <= 4096
我们可以对题目中所描述的内容构建有向图:将每个点看作一个长度为
在这个有向图中,一共有
时间复杂度
class Solution:
def crackSafe(self, n: int, k: int) -> str:
def dfs(u):
for x in range(k):
e = u * 10 + x
if e not in vis:
vis.add(e)
v = e % mod
dfs(v)
ans.append(str(x))
mod = 10 ** (n - 1)
vis = set()
ans = []
dfs(0)
ans.append("0" * (n - 1))
return "".join(ans)
class Solution {
private Set<Integer> vis = new HashSet<>();
private StringBuilder ans = new StringBuilder();
private int mod;
public String crackSafe(int n, int k) {
mod = (int) Math.pow(10, n - 1);
dfs(0, k);
ans.append("0".repeat(n - 1));
return ans.toString();
}
private void dfs(int u, int k) {
for (int x = 0; x < k; ++x) {
int e = u * 10 + x;
if (vis.add(e)) {
int v = e % mod;
dfs(v, k);
ans.append(x);
}
}
}
}
class Solution {
public:
string crackSafe(int n, int k) {
unordered_set<int> vis;
int mod = pow(10, n - 1);
string ans;
function<void(int)> dfs = [&](int u) {
for (int x = 0; x < k; ++x) {
int e = u * 10 + x;
if (!vis.count(e)) {
vis.insert(e);
dfs(e % mod);
ans += (x + '0');
}
}
};
dfs(0);
ans += string(n - 1, '0');
return ans;
}
};
func crackSafe(n int, k int) string {
mod := int(math.Pow(10, float64(n-1)))
vis := map[int]bool{}
ans := &strings.Builder{}
var dfs func(int)
dfs = func(u int) {
for x := 0; x < k; x++ {
e := u*10 + x
if !vis[e] {
vis[e] = true
v := e % mod
dfs(v)
ans.WriteByte(byte('0' + x))
}
}
}
dfs(0)
ans.WriteString(strings.Repeat("0", n-1))
return ans.String()
}