There is a box protected by a password. The password is n digits, where each letter can be one of the first k digits 0, 1, ..., k-1.

You can keep inputting the password, the password will automatically be matched against the last n digits entered.

For example, assuming the password is "345", I can open it when I type "012345", but I enter a total of 6 digits.

Please return any string of minimum length that is guaranteed to open the box after the entire string is inputted.

Example 1:

Input: n = 1, k = 2
Output: "01"
Note: "10" will be accepted too.

Example 2:

Input: n = 2, k = 2
Output: "00110"
Note: "01100", "10011", "11001" will be accepted too.

Note:

  1. n will be in the range [1, 4].
  2. k will be in the range [1, 10].
  3. k^n will be at most 4096.

这道题说的是给了k个数字,值为0到k-1,可以组成n位密码。让我们找一个万能钥匙串,能破解任意的n位密码组合,这里对于破解的定义为只要密码是钥匙串的子串就可以破解了,要求出最短的一个万能钥匙串。来看一个例子,n=2,k=2,那么密码的组合有四种,

,,,

所以 00110 就是一种钥匙串,因为密码  (110),  (010),  (001),  (000), 分别都包括在钥匙串中。可以发现,为了尽可能的使钥匙串变短,所以密码之间尽可能要相互重叠,比如 00 和 01,就共享一个0,如果是3个数,012 和 120 共享两个数 "12",再进一步们可以发现,两个长度为n的密码最好能共享 n-1 个数字,这样累加出来的钥匙串肯定是最短的。

密码共有n位,每一个位可以有k个数字,总共不同的密码总数就有k的n次方个。思路是先从n位都是0的密码开始,取出钥匙串的最后 n-1 个数字,然后在后面依次添加其他数字,用一个 HashSet 来记录所有遍历过的密码,这样如果不在集合中,说明是一个新密码,而生成这个新密码也只是多加了一个数字,能保证钥匙串最短,这是一种贪婪的解法,相当的巧妙,就拿题目中的例子2来说明吧,n=2, k=2,最多有4个密码。开始时 res 初始化为 00,需要遍历4次。第一次遍历时,先取出最后一个数字0,此时先尝试再后面添加1,可组成新密码 01,不在 HashSet 中,将其加入 HashSet,并且将这个1加到 res 后面,变为 001,然后断开内部 for 循环。开始进行第2次遍历,取出 res 中最后一个数字1,先尝试在后面添加1,可组成新密码 11,不在 HashSet 中,将其加入 HashSet,并且将这个1加到 res 后面,变为 0011,然后断开内部 for 循环。开始进行第3次遍历,取出 res 中最后一个数字1,先尝试在后面添加1,可组成密码 11,已在 HashSet 中,跳过;尝试在后面添加0,可组成密码 10,不在 HashSet 中,将其加入 HashSet,并且将这个0加到 res 后面,变为 00110,然后断开内部 for 循环。开始进行第4次遍历,取出 res 中最后一个数字0,先尝试在后面添加1,可组成密码 01,已在 HashSet 中,跳过;再尝试在后面添加0,可组成密码 00,已在 HashSet 中,跳过,循环结束。这样最终的 res 为 00110 即为符合题意的万能钥匙,参见代码如下:

解法一:

class Solution {
public:
string crackSafe(int n, int k) {
string res = string(n, '');
unordered_set<string> visited{{res}};
for (int i = ; i < pow(k, n); ++i) {
string pre = res.substr(res.size() - n + , n - );
for (int j = k - ; j >= ; --j) {
string cur = pre + to_string(j);
if (!visited.count(cur)) {
visited.insert(cur);
res += to_string(j);
break;
}
}
}
return res;
}
};

来看同一种解法的递归写法,思路和迭代的写法一模一样,写法略有不同而已,参见代码如下:

解法二:

class Solution {
public:
string crackSafe(int n, int k) {
string res = string(n, '');
unordered_set<string> visited{{res}};
helper(n, k, pow(k, n), visited, res);
return res;
}
void helper(int n, int k, int total, unordered_set<string>& visited, string& res) {
if (visited.size() == total) return;
string pre = res.substr(res.size() - n + , n - );
for (int i = k - ; i >= ; --i) {
string cur = pre + to_string(i);
if (visited.count(cur)) continue;
visited.insert(cur);
res += to_string(i);
helper(n, k, total, visited, res);
}
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/753

参考资料:

https://leetcode.com/problems/cracking-the-safe/

https://leetcode.com/problems/cracking-the-safe/discuss/110264/Easy-DFS

https://leetcode.com/problems/cracking-the-safe/discuss/112966/C++-greedy-loop-from-backward-with-explaination

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 753. Cracking the Safe 破解密码的更多相关文章

  1. [LeetCode] Cracking the Safe 破解密码

    There is a box protected by a password. The password is n digits, where each letter can be one of th ...

  2. 【LeetCode】753. Cracking the Safe 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/cracking ...

  3. 753. Cracking the Safe

    There is a box protected by a password. The password is n digits, where each letter can be one of th ...

  4. 如何破解密码的哈希值,破解双MD5密码值

    这是关于我如何破解密码的哈希值1亿2200万* John the Ripper和oclHashcat-plus故事. 这是几个月前,当我看到一条推特:从korelogic约含共1亿4600万个密码的密 ...

  5. windows下hashcat利用GPU显卡性能破解密码

    由于一般密码破解工具的破解速度实在是太慢,而且支持的密码破解协议也不多,暴力破解的话,有的密码1年时间也破不出来,用字典跑的话必须要明文密码在字典里才行,而且密码字典太大的话,也很浪费时间,跑不出来也 ...

  6. 为什么现在更多需要用的是 GPU 而不是 CPU,比如挖矿甚至破解密码?

    作者:Cascade链接:https://www.zhihu.com/question/21231074/answer/20701124来源:知乎著作权归作者所有,转载请联系作者获得授权. 想要理解G ...

  7. 暴力枚举 + 24点 --- hnu : Cracking the Safe

    Cracking the Safe Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit u ...

  8. python 暴力破解密码脚本

    python 暴力破解密码脚本 以下,仅为个人测试代码,环境也是测试环境,暴力破解原理都是一样的, 假设要暴力破解登陆网站www.a.com 用户 testUser的密码, 首先,该网站登陆的验证要支 ...

  9. 破解密码那些事儿(Hacking Secret Ciphers with Python)

    作者:Al Sweigart   我们在电视和电影里头经常能够看到黑客们兴奋的快速敲击键盘,接着毫无意义的数字就在屏幕上飞奔(比如黑客帝国).然后让大家产生了一种奇妙的错觉,做黑客是一件高大上的事情, ...

随机推荐

  1. AutoDesk公司搞的fbx模型格式

    FBX® data exchange technology is a 3D asset exchange format that facilitates higher-fidelity data ex ...

  2. mybatis+postgresql10插入返回主键ID

    MyBatis如果使用useGeneratedKeys去生成自增列会造成不成功,因为官方提供只支持这些数据库:mybatis generatedkeys,那么如果要用在oracle和postgresq ...

  3. Spring源码系列 — Bean生命周期

    前言 上篇文章中介绍了Spring容器的扩展点,这个是在Bean的创建过程之前执行的逻辑.承接扩展点之后,就是Spring容器的另一个核心:Bean的生命周期过程.这个生命周期过程大致经历了一下的几个 ...

  4. [CrackMe]160个CrackMe之001

    吾爱破解专题汇总:[反汇编练习]160个CrackME索引目录1~160建议收藏备用 一.Serial/Name 之 暴力破解 1. 熟悉界面:很常规的一个界面,输入完账号密码之后会进行验证.  2. ...

  5. SAP PI接口(RFC类型)在函数字段修改或增加后,出现字段映射错误问题

    在解决标题所言问题之前,我们先回头看看RFC和sproxy这两种接口的优缺点. 关于PI接口的实现,目前我了解到的各大国企项目像中海油.中石化.国网等,普遍实现方式是RFC和代理类sproxy这两种. ...

  6. WPF MVVM框架(5)

    前面几章节所讲到的内容, 基本上属于前端XAML的使用方法, 那么本章及后面的章节, 则会侧重于UI与业务分离如何分离 . UI与业务逻辑之间的互操作性,, 下面将介绍WPF中, 比较主流的MVVM框 ...

  7. windows小乌龟和git使用

    一.安装git for windows 首先下载git for windows客户端http://msysgit.github.io/ 安装过程没什么特别的,不停next就ok了     图太多就不继 ...

  8. CSS 选择器大全

    在CSS中,选择器是用于选择要设置样式的元素的模式. 选择器 例子 描述 .class .intro 选择class=“intro”的所有元素 #id #firstname 选择id=“firstna ...

  9. dtd语法

    dtd语法 <!ELEMENT 元素名 约束> //简单元素三种:没有子元素的元素 eg: <!ELEMENT name (#PCDATA)> (#PCDATA):约束name ...

  10. iframe子元素无法全屏

    最近做的项目中遇到的问题: 在最新的Chrome浏览器中,全屏功能正常 在旧版本Chrome浏览器中(与最新版版本号相差二十左右),全屏功能无效 在IE11浏览器中,全屏功能无效 反复排查,发现该项目 ...