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] 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. Java集合:TreeMap源码剖析

    一.概念 TreeMap是基于红黑树结构实现的一种Map,要分析TreeMap的实现首先就要对红黑树有所了解. 要了解什么是红黑树,就要了解它的存在主要是为了解决什么问题,对比其他数据结构比如数组,链 ...

  2. 爬虫(scrapy第一篇)

    ---------------------------------------------------------------------------------------------------- ...

  3. zabbix通过SNMP监控服务器硬件及构建触发器

    公司的服务器没装系统无法使用IPMI协议来监控服务器硬件信息,所以我们使用SNMP来获取,下面介绍如何通过SNMP监控服务器硬件信息. 1.HP服务器进入iLO开启SNMP协议. 2.查看服务器温度信 ...

  4. wpf研究之道-datagrid控件(1)

    "想要说些什么 又不知从何说起",每当想要写一些关于wpf的文章,总是沉思良久,怕自己写不好.今天我想要说的是wpf中datagrid控件.我们先来看看它在整个类的层次结构:   ...

  5. python内置函数 divmod()

    先来看一下builtins.py中的代码: def divmod(x, y): # known case of builtins.divmod """ Return th ...

  6. 笔试常考--浏览器兼容性问题及解决方案(CSS)

    问题一:不同浏览器的标签默认的外补丁和内补丁不同 问题现象:随便写几个标签,不加样式控制的情况下,各自的margin 和padding差异较大. 解决方案:css里加: ;;} 备注:这个是最常见的也 ...

  7. C第十八次课

    总结知识点: 指针 1.指针变量 指针变量的定义:例8.1 指针变量的引用:例8.2: 指针变量作为函数参数:例8.3 swap函数,例8.4 比较排序函数 2.指针数组 数组元素的指针:int *p ...

  8. 【Alpha版本】冲刺阶段 - Day5 - 破浪

    今日进展 袁逸灏:解决音乐播放问题以及跳转问题.(5h) 刘伟康:大致检查了测试规范,参考了其他 alpha 阶段的博客.(1h) 刘先润:解决了敌车与障碍物溢出边界的代码问题,给用户车辆增加了火焰喷 ...

  9. django获取ip与数据重复性判定

    获取ip if request.META.has_key('HTTP_X_FORWARDED_FOR'): ip_c = request.META['HTTP_X_FORWARDED_FOR'] el ...

  10. HTML5的新的结构元素介绍

    HTML5的新的结构元素介绍 一.HTML5与HTML4的区别 1. 取消了一些过时的HTML4的标签 其中包括纯粹显示效果的标记,如<font>和<center>,它们已经被 ...