LeetCode 753. Cracking the Safe
所有可能的密码总数 k^n,如果把这些密码都拼起来,长度 n*k^n
如果每个密码与前一个密码共用 n-1 位,那么长度缩减为 k^n + (n-1)
上述字符串也被称为 De Bruijn sequence。
所以问题转变为,如果得到这个序列。很容易想到转化为图的问题来做,而且可以转化不同的问题。
-> Hamilton Path
如果把所有可能的密码分别作为节点,通过共用 n-1 位转换得到的节点间添加有向边 (因此每个节点有 k 条边),如 X000 -1-> 0001 。原问题就转化为了寻找 Hamilton Path 的问题。但是判断以及寻找 Hamilton Path 是 NP-Complete 问题,因此只能暴力回溯去做。最后的答案就是 初始选择的节点+转换时添加位。
由于本题的图的对称性以及别的较好的性质,Hamilton Path 是一定存在的,而且甚至不需要回溯就能找到路径。但是由于主题思路还是回溯,回溯部分代码还是添加上使得思路更加清晰。
class Solution { public:string res;string crackSafe(int n, int k) {int size=pow(k,n); // number of all possible passwords res.resize(n,'0');unordered_set<string> visited{res};if (dfs(string(n,'0'),size,k,visited))return res;return "";}bool dfs(string node, int size, int k, unordered_set<string> &visited){if (visited.size()==size) return true;// n-1 digits of last passwordstring suffix=node.substr(1);for (char ch='0';ch<'0'+k;++ch){string newNode=suffix+ch;if (!visited.count(newNode)){visited.insert(newNode); res.push_back(ch);if (dfs(newNode,size,k,visited)) return true;res.pop_back(); visited.erase(newNode);}}return false;} };
-> Euler Circuit
每个密码的最后 n-1 位作为节点,通过共用这 n-1 位转换得到的节点间添加有向边,每个节点同样有 k 条边,如 000 -1-> 001 。原问题就转化为寻找 Euler Path 的问题,因为每个节点加上出去边上的那一位就是一种密码,要得到所有密码,必须访问每条边一次。要最短的字符串,就是 Euler Circuit 的问题。Eular Circuit 是可以在多项式时间内有解的。
Hierholzer's Algorithm 可以 O(V+E) 内找到 Euler Circuit,详见以下链接。由于链接里是把节点一次print出来,所以更加繁琐一点。https://www.geeksforgeeks.org/hierholzers-algorithm-directed-graph/
对于本题,我们只需要任意一个点加上所有路径上的字符即可。所有路径可以通过后序遍历轻松得到 (和上述链接做法本质一样)。其实连reverse都不用,因为是无向图。
class Solution { public:string res;string crackSafe(int n, int k) {unordered_set<string> visited;res = "";dfs(string(n-1,'0'),k,visited);reverse(res.begin(),res.end());return string(n-1,'0')+res;}void dfs(string node, int k, unordered_set<string> &visited){for (char ch='0';ch<'0'+k;++ch){string newNode=node+ch;if (!visited.count(newNode)){visited.insert(newNode); dfs(newNode.substr(1),k,visited);res.push_back(ch);}}} };
时间复杂度 O(k*k^n),因为每次找边的时候,是for循环枚举的。如果用链表或者别的方式存储,时间复杂度为 O(k^n)。纯粹是for循环更好些才这么做的。
Reference:
https://leetcode.com/problems/cracking-the-safe/discuss/110265/Having-trouble-understanding-it-Try-this.
转载于:https://www.cnblogs.com/hankunyan/p/11009810.html
LeetCode 753. Cracking the Safe相关推荐
- 【Leetcode】753. Cracking the Safe
题目地址: https://leetcode.com/problems/cracking-the-safe/ 给定一个正整数nnn和一个正整数kkk,题目保证k<10k<10k<10 ...
- 753 Cracking the Safe
方法一 Hierholzer's Algorithm 相关概念: 1 欧拉路径:在无向图中,每个边只经过一次,形成的路径.在有向图中,是指每条有向边只使用一次,形成的路径. 2 欧拉回路:欧拉路径是一 ...
- Leetcode 753. 破解保险箱 C++
Leetcode 753. 破解保险箱 题目 有一个需要密码才能打开的保险箱.密码是 n 位数, 密码的每一位是 k 位序列 0, 1, -, k-1 中的一个 . 你可以随意输入密码,保险箱会自动记 ...
- leetcode 802. Find Eventual Safe States | 802. 找到最终的安全状态(有向图DFS)
题目 https://leetcode.com/problems/find-eventual-safe-states/ 题解 用 circle 表示所有环上节点和所有能到达环的节点. DFS,实际上每 ...
- LeetCode之Find Eventual Safe States(Kotlin)
问题: In a directed graph, we start at some node and every turn, walk along a directed edge of the gra ...
- Java实现 LeetCode 753 破解保险箱(递归)
753. 破解保险箱 有一个需要密码才能打开的保险箱.密码是 n 位数, 密码的每一位是 k 位序列 0, 1, -, k-1 中的一个 . 你可以随意输入密码,保险箱会自动记住最后 n 位输入,如果 ...
- LeetCode 753. 破解保险箱(有向欧拉图,计算机译码)
有一个需要密码才能打开的保险箱.密码是 n 位数, 密码的每一位是 k 位序列 0, 1, -, k-1 中的一个 . 你可以随意输入密码,保险箱会自动记住最后 n 位输入,如果匹配,则能够打开保险箱 ...
- taoqick 搜索自己CSDN博客
L1 L2正则化和优化器的weight_decay参数 kaiming初始化的推导 Pytorch动态计算图 Pytorch自动微分机制 PyTorch中在反向传播前为什么要手动将梯度清零? 通俗讲解 ...
- leetcode刷题规划
LeetCode精华题目列表[刷题规划系列] – TuringPlanet 目录 算法题到底在考察什么? 题目列表 Array String Linked List Queue Stack Advan ...
最新文章
- j.u.c.locks.AbstractQueuedSynchronizer.Node
- 如何在Vim中复制到剪贴板?
- 设计一个函数能够取出字符串中指定的字符
- java return none,返回列表结果为none
- hbase中的row key_hbase中RowKey的设计规则
- mysql5.7环境,MySQL-5.7-线上生产环境部署
- Windows Phone开发(29):隔离存储C 转:http://blog.csdn.net/tcjiaan/article/details/7447469...
- intellij idea 中去除 @Autowired 注入对象带来的红色下划线报错提示
- apache 支持.htaccess重写url
- PyCharm+Python3转换xls文件为xlsx文件格式
- 运算器为计算机提供了计算与逻辑,【单选题】运算器为计算机提供了计算与逻辑功能,因此称它为()....
- 《图形学》实验一:钻石图案
- java.net.SocketException: Connection reset 问题分析
- Arduino: AD模数转换详解和电路搭建以及示例代码
- 计算机科学与技术用惠普星15,11代酷睿满血出击 快来GET蔡徐坤同款惠普星14吧...
- 【资源】DNW驱动,Win7 64位可用
- XML文档定义有几种形式?解析XML文档有哪几种方式?
- git pull 时每次都要输入用户名和密码的解决办法
- php 路由器设置密码,为防蹭网宽带密码修改之后无线路由器设置教程
- linux c编程文件枷锁