【LeetCode】753. Cracking the Safe 解題報告(Python)
題目描述:
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"
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:
- n will be in the range [1, 4].
- k will be in the range [1, 10].
- k^n will be at most 4096.
題目大意
題目描述是一個智慧門鎖,這個門鎖只識別最近的n個字元,只要有連續的n個字元輸入對了,前面無論輸入什麼都無所謂。那麼,讓我們求一個最短的萬能鑰匙串,能破解這個門鎖的所有可能密碼。
解題方法
顯而易見,如果要這個萬能鑰匙串足夠短,那麼可以預料的是,每個密碼都複用前面的密碼,那麼最優情況下就是,每個密碼複用前面的n - 1位密碼。額,這個數學問題叫做De Bruijin sequence
,已經證明了每個可能的密碼都可以在一個萬能鑰匙串中出現並且只出現一次。(Leetcode出這樣的題也是讓人沒轍)
n位的密碼鎖,每個位置可以有k個數,所以總的可能性是k ^ n個。然後我們從前n位是0的狀態開始,每次在後面新增一個新的字元,同時使用set儲存這個出現過的新密碼。當新密碼的種類數等於 k ^ n時,搜尋截止。
數學上已經鄭明,這樣的串是最短的串,而且,能解決所有可能的密碼數。
python由於是值傳遞,可以通過給函式傳list的方式,直接修改list內會導致外邊的List也變化,但是傳string不行。string是不可變的物件,函式內部修改string不會影響到外邊。因此,如果需要動態生成字串,可以把string變成list當做函式的引數。
時間複雜度是O(Nlog(N)),空間複雜度是O(N)。
class Solution(object):
def crackSafe(self, n, k):
"""
:type n: int
:type k: int
:rtype: str
"""
res = ["0"] * n
size = k ** n
visited = set()
visited.add("".join(res))
if self.dfs(res, visited, size, n, k):
return "".join(res)
return ""
def dfs(self, res, visited, size, n, k):
if len(visited) == size:
return True
node = "".join(res[len(res) - n + 1:])
for i in range(k):
node = node + str(i)
if node not in visited:
res.append(str(i))
visited.add(node)
if self.dfs(res, visited, size, n, k):
return True
res.pop()
visited.remove(node)
node = node[:-1]
參考資料:
日期
2018 年 10 月 5 日 —— 轉眼假期要結束了!!