type
status
date
slug
summary
tags
category
icon
password
创建时间
Jan 15, 2025 05:09 AM
有一个需要密码才能打开的保险箱。密码是
n
位数, 密码的每一位都是范围 [0, k - 1]
中的一个数字。保险箱有一种特殊的密码校验方法,你可以随意输入密码序列,保险箱会自动记住 最后
n
位输入 ,如果匹配,则能够打开保险箱。- 例如,正确的密码是
"345"
,并且你输入的是"012345"
: - 输入
0
之后,最后3
位输入是"0"
,不正确。 - 输入
1
之后,最后3
位输入是"01"
,不正确。 - 输入
2
之后,最后3
位输入是"012"
,不正确。 - 输入
3
之后,最后3
位输入是"123"
,不正确。 - 输入
4
之后,最后3
位输入是"234"
,不正确。 - 输入
5
之后,最后3
位输入是"345"
,正确,打开保险箱。
在只知道密码位数
n
和范围边界 k
的前提下,请你找出并返回确保在输入的 某个时刻 能够打开保险箱的任一 最短 密码序列 。1 <= n <= 4
1 <= k <= 10
1 <= kn <= 4096
欧拉路
官方解释
例子:00010020110120210221112122200
000 001 010 100 002 020 201 011 110 101 012 120 202 021 210 102 022 221 211 111 112 121 212 122 222 220 200
我们使用 Hierholzer 算法找欧拉回路:
- 我们从节点 开始,任意地经过还未经过的边,直到我们「无路可走」(死胡同)。此时我们一定回到了节点 ,这是因为所有节点的入度和出度都相等。
- 回到节点 之后,我们得到了一条从 开始到 结束的回路,这条回路上仍然有些节点有未经过的出边。我么从某个这样的节点 开始,继续得到一条从 开始到 结束的回路,再嵌入之前的回路中;
- 以此类推,直到没有节点有未经过的出边,此时我们就找到了一条欧拉回路。
class Solution { public: string crackSafe(int n, int k) { unordered_set<int> vis; string ans; int highest = pow(10, n - 1); function<void(int)> dfs = [&](int node) { // 遍历当前节点的所有边 for (int x = 0; x < k; x++) { int tmp = node * 10 + x; if (!vis.contains(tmp)) { vis.insert(tmp); // 递归下去 dfs(tmp % highest); // 递归返回后,再更新,栈的结构。也就是一条路走到黑,路走完了。 ans += (x + '0'); } } }; dfs(0); ans += string(n - 1, '0'); return ans; } };