leetcode 753.破解保险箱

https://leetcode.cn/problems/cracking-the-safe/
已知:密码有n位,每一位可以从0到k-1中的数中选取
求:解出密码最多要输入多长的字符串?
例:n=2, k=2 密码有2位,每一位可选0或1,则(一种情况)输入00110保证密码正确——输入已包含00、01、10、11所有结果。
思路:构建一个图,每个节点都是n-1位的密码(如n=3,k=2,那么节点为00、01、10、11),每个节点以0-k-1中的数相连(如01通过1与11相连、通过0与10相连),只需由任意一个节点出发遍历所有的节点后回到该节点,遍历过的边加上该节点就是答案。
图源:Tizzi
实现:由某点出发最后回到该点,可以通过BFS实现,用一个集合判断一个节点是否被访问过,当访问的节点已无节点可以访问则说明已回到起点
由于从n-1个全0密码出发,而n位全0密码不需要经过其他路径得到,可以通过连续多次在起点(终点也行,反正是同一个节点)添加0得到,故最后结果要在开头或结尾加上n-1个0。
ps:从0开始的话开头已经有一个0了,这里由于DFS返回的是逆序的结果(当一个节点没有边再添加该节点),故要在开头添加0,在代码中就是在最后加0。

class Solution {
public:
    int n, k, mod;
    string ans;
    set<int> vis;  //判断每条边是否访问过
    string crackSafe(int N, int K) {
        n = N; k = K; mod = pow(10, n - 1); 
        dfs(0); //从0点出发
        ans += string(n - 1, '0'); //添加最开始的0的前缀
        return ans;
    }
    void dfs(int u) {
        for (int i = 0; i < k; i++) { //对于每个点循环k条边即可
            int v = u * 10 + i; //即边的编号
            if (!vis.count(v)) {
                vis.insert(v);    //标记该边已经访问 
                dfs(v % mod); //边界,节点最大为n-1位数字
                ans += (i+'0'); //添加最后一个数字
                cout<<ans<<endl;
            } 
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值