题目链接
难度:困难 类型: 深度优先搜索
有一个需要密码才能打开的保险箱。密码是 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" 也能打开保险箱。
解题思路
密码接龙
这道题说的是给了k个数字,值为0到k-1,让我们组成n位密码。我们可以发现,为了尽可能的使钥匙串变短,所以我们的密码之间尽可能要相互重叠,
比如00和01,就共享一个0,
如果是3个数,012和120共享两个数”12”,
那么我们可以发现,两个长度为n的密码最好能共享n-1个数字,这样累加出来的钥匙串肯定是最短的。
密码共有n位,每一个位可以有k个数字,那么总共不同的密码总数就有k的n次方个。我们的思路是先从n位都是0的密码开始,取出钥匙串的最后n个数字,然后将最后一个数字依次换成其他数字,我们用一个Set来记录所有遍历过的密码,这样如果不在集合中,说明是一个新密码,而生成这个新密码也只是多加了一个数字,这样能保证我们的钥匙串最短
- 初始一个最小的可能的n-1位的密码,即n-1个0
- 最后一位依次添加0到k-1,组成的n位密码如果未出现过,就把最后一位加入res,并且把这n位密码加入集合seen,表示已经出现过这个密码
- 然后取该n位密码的后n-1位, 进行第2步
- 最后把所有res中的数串起来,再接上n-1个0,接在后面的原因是这段代码用到递归,输出的值是倒序的
代码实现
class Solution(object):
def crackSafe(self, n, k):
"""
:type n: int
:type k: int
:rtype: str
"""
seen = set()
res = []
def dfs(node):
for x in map(str, range(k)):
nei = node + x
if nei not in seen:
seen.add(nei)
dfs(nei[1:])
res.append(x)
dfs('0'*(n-1))
return ''.join(res) + '0'*(n-1)
网友评论