欧拉回路,Hierholzer算法
Last updated
Was this helpful?
Last updated
Was this helpful?
dietpepsi 你这个贱人。。我搞了半天才发现这题不是简单的 DFS,而是欧拉回路。。。
这题其实和我之前用 DFS 处理 topological sort 的代码非常像,主要区别在于存 graph 的方式不同,这里是一个 String 直接连着对应的 next nodes,而且形式是 min heap:
原题给的是 edges,所以图是自己用 hashmap 建的。
min heap 可以自动保证先访问 lexicographical order 较小的;
同时 poll 出来的 node 自动删除,免去了用 List 的话要先 collections.sort 再 remove 的麻烦。
这种以 “edge” 为重心的算法多靠 heap,比如 dijkstra.
首先你要弄明白你面对的是一个神马密码锁,它的特性是这样的: 一个长度为n=4的密码框,一个键盘有k=10个按键,分别是0~9。 你输入0000,系统会验证0000是否是正确密码。 这时候你再输入一个1,不同的密码锁有不同的处理方式 一种会reset,也就是说前面的4个0消失了,你需要继续输入4个数供系统判断。 另一种不会reset,它会验证最近键入的4歌数字,即0001。 我们面对的是后一种。
如果是前一种的话,没啥好想的,破解序列就是4*10000 但是后一种,可以做到长度为10003的破解序列覆盖所有可能的10000个4位数。 题目就是让你找到这个序列。
我觉得这道题在题意明确的情况下,把所有状态看成点,状态之间的转移看成边是比较自然的。 这样就有两种看法,一种就是把4位看成状态,一种就是把3位看成状态。 把4位看成状态的图上面找Hamilton回路,很显然是本题的答案,因为访问了每一个节点一次且只有一次。 把3位看成状态的图上面找欧拉回路可能需要给面试官解释一下。但我觉得还是比较好解释的。 因为每一条边其实代表了一种4位的状态,于是就很好解释了。 那么上面的DFS找欧拉回路的算法就是相当简单有效的解法了。在删除边和查找下一个没有访问的边的复杂度是O(1)的情况下这个算法的复杂度是O(E)的,也就是O(k^n)的,de Buijin构造算法不会比这个复杂度更好。 我这个实现没有用LinkedList或者Hash来保存边的信息,所以每次都是循环所有可能的边,也就是O(k)查找边,所以总的复杂度是O(k^(n+1))。 考虑到 k = 10 n = 4 我觉得没啥问题。