[LeetCode] 753. Cracking the Safe_Hard tag: DFS, backtracking
2021-08-19 10:11 Johnson_强生仔仔 阅读(31) 评论(0) 编辑 收藏 举报There is a safe protected by a password. The password is a sequence of n
digits where each digit can be in the range [0, k - 1]
.
The safe has a peculiar way of checking the password. When you enter in a sequence, it checks the most recent n
digits that were entered each time you type a digit.
- For example, the correct password is
"345"
and you enter in"012345"
:- After typing
0
, the most recent3
digits is"0"
, which is incorrect. - After typing
1
, the most recent3
digits is"01"
, which is incorrect. - After typing
2
, the most recent3
digits is"012"
, which is incorrect. - After typing
3
, the most recent3
digits is"123"
, which is incorrect. - After typing
4
, the most recent3
digits is"234"
, which is incorrect. - After typing
5
, the most recent3
digits is"345"
, which is correct and the safe unlocks.
- After typing
Return any string of minimum length that will unlock the safe at some point of entering it.
Example 1:
Input: n = 1, k = 2 Output: "10" Explanation: The password is a single digit, so enter each digit. "01" would also unlock the safe.
Example 2:
Input: n = 2, k = 2 Output: "01100" Explanation: For each possible password: - "00" is typed in starting from the 4th digit. - "01" is typed in starting from the 1st digit. - "10" is typed in starting from the 3rd digit. - "11" is typed in starting from the 2nd digit. Thus "01100" will unlock the safe. "01100", "10011", and "11001" would also unlock the safe.
Constraints:
1 <= n <= 4
1 <= k <= 10
1 <= kn <= 4096
Ideas:
1. 要有k ^ n 种情况,如果要最短的话,那么就让前面n - 1个string作为prefix,依次在后面加上一个string,其实不知道为啥这样就能保证肯定是有,说是有euler path, 有空再看看
2. 从 ans = "0" * n 开始,依次以ans[-n + 1:]作为prefix然后来看是否可以加入str(i)
3. 再用backtracking来将所有的可能性全部弄出来; note(这里返回ans, 如果ans只是作为parameter来传进去的话,在function里面改变ans,不会改变原ans)
4. 另外需要注意的是当n == 1 的edge case
Code:
class Solution: def crackSafe(self, n: int, k: int) -> str: ans = "0" * n visited = set([ans]) times = k ** n return self.dfs(ans, visited, times, n, k) def dfs(self, ans, visited, times, n, k): if len(visited) == times: return ans lastDigits = ans[-n + 1:] for i in range(k): newDigits = lastDigits + str(i) if n != 1 else str(i) if newDigits not in visited: visited.add(newDigits) ans += str(i) temp = self.dfs(ans, visited, times, n, k) if temp: return temp visited.remove(newDigits) ans = ans[:-1]