【Leetcode】753. Cracking the Safe

题目地址:

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

给定一个正整数 n n n和一个正整数 k k k,题目保证 k < 10 k<10 k<10,要求给出一个序列 s s s,只含 0 ∼ k − 1 0\sim k-1 0k1,使得任意长 n n n的只由 0 ∼ k − 1 0\sim k-1 0k1组成的序列都是 s s s的子串。返回任一符合要求的答案即可。

其实是欧拉回路问题。一共有 k n k^n kn种可能的序列,首先理论上,如果我们能使得,除了前 n − 1 n-1 n1位长度不够,但是从第 n n n位开始,后面每次添加一个数字,得到的长 n n n后缀都是一种子串,并且每次添加完一个数字后都能得到不同的子串,那么这样得出的序列 s s s一定是最短的,并且不可能更短了。这样的 s s s的长度是 n − 1 + k n n-1+k^n n1+kn。我们看能否构造出这个 s s s

现在将所有只含 0 ∼ k − 1 0\sim k-1 0k1的长 n − 1 n-1 n1的字符串看成是顶点,比如 u u u v v v是两个长 n − 1 n-1 n1的字符串,并且存在边 u → v u\to v uv当且仅当 u u u的长 n − 2 n-2 n2的后缀等于 v v v的长 n − 2 n-2 n2的前缀( u → v u\to v uv可以是自环。这里的意思是将所有长 n n n的字符串看成边,该边可以用 u u u字符串append上 v v v的最后一个字符得到)。首先,这个有向图一定含欧拉回路。第一,其每个顶点后面可以加 k k k个不同字符,前面也可以加 k k k个不同字符,所以每个顶点入度等于出度;第二,任意两个点之间一定是连通的,例如对于"abc"要走到"xyz",可以"abc" -> "bcx" -> "cxy" -> "xyz",其余情况可以类似做。所以这个图是个欧拉图,从而从任一点出发都存在欧拉回路,由于欧拉回路里每条边只走一次,所以每走一条边就能得到一个全新的长 n n n 0 ∼ k − 1 0\sim k-1 0k1的排列。随便取一个出发点,设这个点是字符串 t t t,每走一条边,就将该边的最后一个字符append到 t t t后面,走完欧拉回路之后形成的字符串就是答案。代码如下:

import java.util.HashSet;
import java.util.Set;

public class Solution {
    public String crackSafe(int n, int k) {
        String start = "0".repeat(n - 1);
        StringBuilder sb = new StringBuilder();
        dfs(start, new HashSet<>(), k, sb);
        // 最后可以不用翻转,因为任意答案的翻转肯定也是答案,是左右对称的
        return sb + start;
    }
    
    private void dfs(String s, Set<String> set, int k, StringBuilder sb) {
        for (int i = 0; i < k; i++) {
        	// 枚举所有出边
            String next = s + i;
            // 如果该边没走过,则走之
            if (set.add(next)) {
            	// 下一个点是next[1:]
                dfs(next.substring(1), set, k, sb);
                sb.append(i);
            }
        }
    }
}

时空复杂度 O ( n + k n ) O(n+k^n) O(n+kn)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值