前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Cracking the Safe

Cracking the Safe

作者头像
用户1147447
发布2019-05-26 00:13:31
4080
发布2019-05-26 00:13:31
举报
文章被收录于专栏:机器学习入门

LWC 64: 753. Cracking the Safe

Problem:

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:

  • n will be in the range [1, 4].
  • k will be in the range [1, 10].
  • k^n will be at most 4096.

思路: 此题是贪心,比如n = 4, k = 3的情况下,初始构造了”0000”,为了让密码序列最小,我们最大化利用”0000”中的后三位,这样一来就有三种情况:”00000”和”00001”和”00002”,其中第一种是重复的,所以直接舍去。接着继续看最后三位并构造。典型的子问题,用dfs解决。

这里讲些细节问题,先来看初始版本:

初始Java版本:

代码语言:javascript
复制
    public String crackSafe(int n, int k) {
        int size = (int) Math.pow(k, n);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; ++i) {
            sb.append("0");
        }
        String init = sb.toString();
        Set<String> vis = new HashSet<>();
        vis.add(init);
        ans = init;
        valid = false;
        int len = n - 1;
        dfs(init, vis, k, size, len);
        return ans;
    }

    String ans;
    boolean valid = false;
    void dfs(String init, Set<String> vis, int k, int size, int len) {
        if (vis.size() == size) {
            ans = init;
            valid = true;
        }
        else {
            if (valid) return;
            int n = init.length();
            for (int j = 0; j < k; ++j) {
                String ns = init.substring(n - len, n) + j;
                if (!vis.contains(ns)) {
                    String nxt = new String(init + j);
                    vis.add(ns);
                    dfs(nxt, vis, k, size, len);
                    vis.remove(ns);
                }
            }
        }
    }

stackoverflow了,堆栈溢出,后来找了下原因,是因为这句话:

代码语言:javascript
复制
String nxt = new String(init + j);

为了让递归返回的时候状态还原,我使用了clone的方法,但这条语句占了大量的内存,即使在指定递归层数内,但也容易stackoverflow。所以做下优化:

代码语言:javascript
复制
    String ans;
    boolean dfs(String init, Set<String> vis, int k, int size, int len) {
        if (vis.size() == size) {
            ans = init;
            return true;
        }
        else {
            int n = init.length();
            for (int j = 0; j < k; ++j) {
                String ns = init.substring(n - len, n) + j;
                if (!vis.contains(ns)) {
                    vis.add(ns);
                    init = init + j;
                    if (dfs(init, vis, k, size, len)) return true;
                    vis.remove(ns);
                    init = init.substring(0, init.length() - 1);
                }
            }
        }
        return false;
    }

这样就能AC了,但需要注意状态还原。不过你可以直接在参数中传值,这样不会影响init!

代码如下:

代码语言:javascript
复制
    String ans;
    boolean dfs(String init, Set<String> vis, int k, int size, int len) {
        if (vis.size() == size) {
            ans = init;
            return true;
        }
        else {
            int n = init.length();
            for (int j = 0; j < k; ++j) {
                String ns = init.substring(n - len, n) + j;
                if (!vis.contains(ns)) {
                    vis.add(ns);
                    if (dfs(init + j, vis, k, size, len)) return true;
                    vis.remove(ns);
                }
            }
        }
        return false;
    }

Python版本:

代码语言:javascript
复制
    def crackSafe(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: str
        """
        goal = k ** n
        init = "0" * n
        self.ans = init
        vis = set()
        vis.add(init)

        def dfs(init, vis, n, k, goal):
            if goal == len(vis):
                self.ans = init
                return True
            else:
                nlen = len(init)
                for i in range(k):
                    ns = init[nlen - n + 1 : nlen] + str(i)
                    if ns not in vis:
                        vis.add(ns)
                        if (dfs(init[:] + str(i), vis, n, k, goal)): return True
                        vis.remove(ns)
            return False

        dfs(init, vis, n, k, goal)
        return self.ans
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017年12月24日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • LWC 64: 753. Cracking the Safe
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档