Leetcode 753. Cracking the Safe

Problem:

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.

Solution:

  这道题thumb down的次数大于thumb up的次数,可见这道题不是很好。对于这道题,总共有k^n种可能的排列,我们现在要把它组合成一个长度为k^n+n-1的字符串,使得所有的排列都是这个字符串的子串。对于这个问题,常规思路是用backtrace,其时间复杂度为k^(k^n),时间复杂度相当高。而答案使用了一种贪心算法,对于下一个要添加的字符s[i],从大到小找到s[i-n+1]到s[i]的未使用过的子串,比如00之后,从1到0找到第一个未使用的子串01,将1添加到末尾变为001。虽然这个算法可行,但对于这道题来说,我们很难找到一种从暴力解法到可优化解法的思考过程,对于这个算法是否可行我们也没有办法证明。因此,对于这道题,我更多的觉得只要记住这种解法即可。

Code:

 1 class Solution {
 2 public:
 3     string crackSafe(int n, int k) {
 4         string res = string(n, '0');
 5         unordered_set<string> visited{{res}};
 6         for (int i = 0; i < pow(k, n); ++i) {
 7             string pre = res.substr(res.size() - n + 1, n - 1);
 8             for (int j = k - 1; j >= 0; --j) {
 9                 string cur = pre + to_string(j);
10                 if (!visited.count(cur)) {
11                     visited.insert(cur);
12                     res += to_string(j);
13                     break;
14                 }
15             }
16         }
17         return res;
18     }
19 };

猜你喜欢

转载自www.cnblogs.com/haoweizh/p/10262190.html