Leetcode 753. Cracking the Safe
阿新 • • 發佈:2019-01-13
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"
"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:
n
will be in the range[1, 4]
.k
will be in the range[1, 10]
.k^n
will be at most4096
.
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 };