• [LeetCode] 753. Cracking the Safe 破解密码


    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.

    这道题说的是给了k个数字,值为0到k-1,可以组成n位密码。让我们找一个万能钥匙串,能破解任意的n位密码组合,这里对于破解的定义为只要密码是钥匙串的子串就可以破解了,要求出最短的一个万能钥匙串。来看一个例子,n=2,k=2,那么密码的组合有四种,

    00011011

    所以 00110 就是一种钥匙串,因为密码 00 (00110), 01 (00110), 10 (00110), 11 (00110), 分别都包括在钥匙串中。可以发现,为了尽可能的使钥匙串变短,所以密码之间尽可能要相互重叠,比如 00 和 01,就共享一个0,如果是3个数,012 和 120 共享两个数 "12",再进一步们可以发现,两个长度为n的密码最好能共享 n-1 个数字,这样累加出来的钥匙串肯定是最短的。

    密码共有n位,每一个位可以有k个数字,总共不同的密码总数就有k的n次方个。思路是先从n位都是0的密码开始,取出钥匙串的最后 n-1 个数字,然后在后面依次添加其他数字,用一个 HashSet 来记录所有遍历过的密码,这样如果不在集合中,说明是一个新密码,而生成这个新密码也只是多加了一个数字,能保证钥匙串最短,这是一种贪婪的解法,相当的巧妙,就拿题目中的例子2来说明吧,n=2, k=2,最多有4个密码。开始时 res 初始化为 00,需要遍历4次。第一次遍历时,先取出最后一个数字0,此时先尝试再后面添加1,可组成新密码 01,不在 HashSet 中,将其加入 HashSet,并且将这个1加到 res 后面,变为 001,然后断开内部 for 循环。开始进行第2次遍历,取出 res 中最后一个数字1,先尝试在后面添加1,可组成新密码 11,不在 HashSet 中,将其加入 HashSet,并且将这个1加到 res 后面,变为 0011,然后断开内部 for 循环。开始进行第3次遍历,取出 res 中最后一个数字1,先尝试在后面添加1,可组成密码 11,已在 HashSet 中,跳过;尝试在后面添加0,可组成密码 10,不在 HashSet 中,将其加入 HashSet,并且将这个0加到 res 后面,变为 00110,然后断开内部 for 循环。开始进行第4次遍历,取出 res 中最后一个数字0,先尝试在后面添加1,可组成密码 01,已在 HashSet 中,跳过;再尝试在后面添加0,可组成密码 00,已在 HashSet 中,跳过,循环结束。这样最终的 res 为 00110 即为符合题意的万能钥匙,参见代码如下:

    解法一:

    class Solution {
    public:
        string crackSafe(int n, int k) {
            string res = string(n, '0');
            unordered_set<string> visited{{res}};
            for (int i = 0; i < pow(k, n); ++i) {
                string pre = res.substr(res.size() - n + 1, n - 1);
                for (int j = k - 1; j >= 0; --j) {
                    string cur = pre + to_string(j);
                    if (!visited.count(cur)) {
                        visited.insert(cur);
                        res += to_string(j);
                        break;
                    }
                }
            }
            return res;
        }
    };

    来看同一种解法的递归写法,思路和迭代的写法一模一样,写法略有不同而已,参见代码如下:

    解法二:

    class Solution {
    public:
        string crackSafe(int n, int k) {
            string res = string(n, '0');
            unordered_set<string> visited{{res}};
            helper(n, k, pow(k, n), visited, res);
            return res;
        }
        void helper(int n, int k, int total, unordered_set<string>& visited, string& res) {
            if (visited.size() == total) return;
            string pre = res.substr(res.size() - n + 1, n - 1);
            for (int i = k - 1; i >= 0; --i) {
                string cur = pre + to_string(i);
                if (visited.count(cur)) continue;
                visited.insert(cur);
                res += to_string(i);
                helper(n, k, total, visited, res);
            }
        }
    };

    Github 同步地址:

    https://github.com/grandyang/leetcode/issues/753

    参考资料:

    https://leetcode.com/problems/cracking-the-safe/

    https://leetcode.com/problems/cracking-the-safe/discuss/110264/Easy-DFS

    https://leetcode.com/problems/cracking-the-safe/discuss/112966/C++-greedy-loop-from-backward-with-explaination

    LeetCode All in One 题目讲解汇总(持续更新中...)

  • 相关阅读:
    网络安装Centos的方法
    命令源码文件——Golang
    mosquitto: error while loading shared libraries: libwebsockets.so.12: cannot open shared object file
    centos7安装mysql初始化报错
    MQTT --- 操作行为
    MQTTv5.0 ---AUTH – 认证交换
    MQTT v5.0------SUBSCRIBE 报文
    MQTT --- Retained Message
    inux centos7下源码 tar安装5.7.26详解
    20. 有效的括号
  • 原文地址:https://www.cnblogs.com/grandyang/p/8452361.html
Copyright © 2020-2023  润新知