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:

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

Example 2:

  1. Input: n = 2, k = 2
  2. Output: "00110"
  3. 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 即为符合题意的万能钥匙,参见代码如下:

解法一:

  1. class Solution {
  2. public:
  3. string crackSafe(int n, int k) {
  4. string res = string(n, '');
  5. unordered_set<string> visited{{res}};
  6. for (int i = ; i < pow(k, n); ++i) {
  7. string pre = res.substr(res.size() - n + , n - );
  8. for (int j = k - ; j >= ; --j) {
  9. string cur = pre + to_string(j);
  10. if (!visited.count(cur)) {
  11. visited.insert(cur);
  12. res += to_string(j);
  13. break;
  14. }
  15. }
  16. }
  17. return res;
  18. }
  19. };

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

解法二:

  1. class Solution {
  2. public:
  3. string crackSafe(int n, int k) {
  4. string res = string(n, '');
  5. unordered_set<string> visited{{res}};
  6. helper(n, k, pow(k, n), visited, res);
  7. return res;
  8. }
  9. void helper(int n, int k, int total, unordered_set<string>& visited, string& res) {
  10. if (visited.size() == total) return;
  11. string pre = res.substr(res.size() - n + , n - );
  12. for (int i = k - ; i >= ; --i) {
  13. string cur = pre + to_string(i);
  14. if (visited.count(cur)) continue;
  15. visited.insert(cur);
  16. res += to_string(i);
  17. helper(n, k, total, visited, res);
  18. }
  19. }
  20. };

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] Cracking the Safe 破解密码的更多相关文章

  1. [LeetCode] 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 ...

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

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

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

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

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

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

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

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

  6. python 暴力破解密码脚本

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

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

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

  8. Linux_破解密码-营救模式

    实验用机:CentOS 5.7 破解密码 设置开机启动界面 系统运行级别 营救模式 一.破解密码 root用户可以更改任何用户的密码,普通用户只能修改自己的密码. 步骤: 1.重新启动系统 2.开机倒 ...

  9. day43 mysql 基本管理,[破解密码以及用户权限设置]以及慢日志查询配置

    配置文件:详细步骤, 1,找到mysql的安装包,然后打开后会看到一个my.ini命名的程序,把它拖拽到notepad++里面来打开,(应该是其他文本形式也可以打开,可以试一下),直接拖拽即可打开该文 ...

随机推荐

  1. JS获得一个对象的所有属性和方法

    function displayProp(obj){ var names=""; for(var name in obj){ names+=name+": "+ ...

  2. oracle管理权限和角色

    介绍 这一部分主要看看oracle中如何管理权限和角色,权限和角色的区别在哪里. 当刚刚建立用户时,用户没有任何权限,也不能执行任何操作.如果要执行某种特定的数据库操作,则必需为其授予系统的权限:如果 ...

  3. Python+reuqests自动化接口测试

    1.最近自己在摸索Python+reuqests自动化接口测试,要实现某个功能,首先自己得有清晰的逻辑思路!这样效率才会很快! 思路--1.通过python读取Excel中的接口用例,2.通过pyth ...

  4. IIS 错误代码

    错误码: 1.HTTP 1xx-信息提示 这些状态代码表示临时的响应.客户端在收到常规响应之前,应准备接收一个或多个1xx响应. 100-继续. 101-切换协议. 2xx-成功 这类状态代码表明服务 ...

  5. python中functools.singledispatch的使用

    from functools import singledispatch @singledispatch def show(obj): print (obj, type(obj), "obj ...

  6. NetFPGA-1G-CML Demo --- reference_router_nf1_cml

    环境 deepin 15.4 vivado 15.2 ise 14.6 前期准备 Github Wiki链接:https://github.com/NetFPGA/NetFPGA-public/wik ...

  7. 利用yield 实现Xrange功能

    def xrange(n): start = 0 while True: if start>n: return yield start start+=1 obj = xrange(5) n1 = ...

  8. 最短路算法模板SPFA、disjkstra、Floyd

    朴素SPFA(链表建边) #include <iostream> #include <cstdio> #include <cstring> #include < ...

  9. Count on a tree

    bzoj  2588: Spoj 10628. Count on a tree http://www.lydsy.com/JudgeOnline/problem.php?id=2588 Descrip ...

  10. 一句话了解JAVA与大数据之间的关系

    大数据无疑是目前IT领域的最受关注的热词之一.几乎凡事都要挂上点大数据,否则就显得你OUT了.如果再找一个可以跟大数据并驾齐驱的IT热词,JAVA无疑是跟大数据并驾齐驱的一个词语.很多人在提到大数据的 ...