概述
描述:
有一个需要密码才能打开的保险箱。密码是 n 位数, 密码的每一位是 k 位序列 0, 1, …, k-1 中的一个 。
你可以随意输入密码,保险箱会自动记住最后 n 位输入,如果匹配,则能够打开保险箱。
举个例子,假设密码是 “345”,你可以输入 “012345” 来打开它,只是你输入了 6 个字符.
请返回一个能打开保险箱的最短字符串。
示例1:
输入: n = 1, k = 2
输出: "01"
说明: "10"也可以打开保险箱。
示例2:
输入: n = 2, k = 2
输出: "00110"
说明: "01100", "10011", "11001" 也能打开保险箱。
提示:
n 的范围是 [1, 4]。
k 的范围是 [1, 10]。
k^n 最大可能为 4096。
思 路 分 析 : color{blue}{思路分析:} 思路分析:这道题的意思是我们将n位长的全排列密码进行“合并”,达到密码的长度最短。比如n == 2,k == 2时,密码只有“00”,“01”,“10”,“11”,我们将“00”与“10”合并可得“100”,再与“01”合并得“10001”,最后与“11”合并得“100011”。不难发现n位长的两个密码最多只能重叠n - 1位,通过n - 1次合并累计,这样得出的密码串肯定是最短的。
class Solution {
public:
string crackSafe(int n, int k) {
const int total = pow(k, n);//全排列总共有k的n次方个
string res = string(n, '0');//初始化
unordered_set<string> visited;//用于记录res中已经构造过了的
visited.insert(res);
//由初始化一直进行构造,直到res包含全排列中所有的元素
for (int i = 1; i < total; ++i) {
//获取res当前最后n - 1个字符用于重复利用,构造下一个还没有构造过的排列
string tempRes = res.substr(res.length() - n + 1, n - 1);
//穷举添加的最后元素
for (int j = k -1; j >= 0; --j) {
string key = tempRes + to_string(j);
if (visited.find(key) == visited.end()) {
//如果这个元素没有构造过
res += to_string(j);
visited.insert(key);//标记构造
break;
}
}
}
return res;
}
};
最后
以上就是俭朴中心为你收集整理的LeetCode 破解保险箱(全排列)的全部内容,希望文章能够帮你解决LeetCode 破解保险箱(全排列)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复