【问题标题】:hackerrank password cracker timeout due to recursion由于递归,hackerrank 密码破解程序超时
【发布时间】:2017-08-27 05:44:50
【问题描述】:

This problem 简单地重申一下:给定一堆字符串和一个目标字符串,给定字符串的所有组合可以组合在一起形成目标字符串,有无重复。

例如

字符串:我们做我们必须做的,因为我们可以

目标:wedowhatwemustbecausewecan

输出:我们做我们必须做的,因为我们可以

我采取的方法是从目标中删除每个较长的单词,直到目标变为空。如果目标变为空,则只返回输出。如果较长的单词无法解决问题,那么尝试使用较短的单词等等。我还使用记忆化来确保如果目标已经尝试过然后返回,与记忆化回溯相同。

这个方法通过了除了 2 之外的所有测试用例,我正在超时。

def recursions(word_map, paswd, output, remember):
    flag = 0
    if len(paswd) == 0:
        return 1
    if paswd in remember:
        return flag
    for char in paswd:
        for word in (word_map[char] if char in word_map else []):
            if paswd.startswith(word):
                output.append(word + " ")
                if recursions(word_map, paswd[len(word):], output, remember):
                    return 1
                output.pop()
        remember[paswd] = 1
    return flag

请帮忙提供一个提示。完整的解决方案是here

【问题讨论】:

  • 代码看起来是正确的,但如果递归太深可能会出现问题。但是在 stackoverflow 上调试问题需要一个特定的问题并在问题中重现问题。
  • 尝试切换到pypy。虽然 pypy 的超时时间远低于 python,但在某些情况下您不会超过它。

标签: python algorithm recursion backtracking memoization


【解决方案1】:

您可以尝试使用动态编程方法标记每个密码的结束位置。首先在较长字符串的开头尝试每个密码。如果它适合在那里标记较长字符串中的结束位置。然后,您可以对较长字符串中的每个位置重复相同的过程,其中先前的位置被标记为结束位置。

希望这可以帮助您入门,我故意遗漏了完整解决方案所需的一些信息,所以如果您仍然卡住,请在 cmets 中告诉我。

编辑这是我所说的一个简短示例。它不允许您重构解决方案,但它显示了如何在没有递归的情况下进行匹配:

passwords = ['foo', 'bar']
login = 'foobar'

ends_here = [False] * len(login)

for i in range(len(ends_here)):

    # Match password at the beginning or if password match
    # ended to previous index
    if i == 0 or ends_here[i - 1]:
        for pw in passwords:
            if login.find(pw, i, i + len(pw)) != -1:
                ends_here[i + len(pw) - 1] = True

print(ends_here)
print('We can match whole login attempt:', ends_here[-1])

输出:

[False, False, True, False, False, True]
We can match whole login attempt: True

编辑仔细查看了问题中提供的代码。问题在于匹配的字符串由目标中包含的字符过滤:for char in paswd:。而不是对目标字符串中的每个字符进行过滤,而是应该对每个 unique 字符进行过滤:for char in set(paswd):。解决这个问题,解决方案运行得更快,但如果根本没有这种过滤,可能会更快,因为较短的字符串的最大数量是 10。

【讨论】:

  • 您能否详细说明,因为我在递归方法中所做的非常相似?
  • @user3053970 添加了关于如何在没有递归的情况下进行匹配的简短示例。不过,您需要对其进行修改,以便在匹配时打印密码,
  • @monster 你是对的,但由于问题是在询问提示,而不是完整的解决方案,因此故意忽略了这一点。
  • 对不起。删除了我的评论,所以不用担心:)
  • @user3053970:添加了解释为什么问题中提供的代码与答案中的示例相比如此缓慢。
猜你喜欢
  • 2016-10-04
  • 1970-01-01
  • 2021-07-03
  • 2018-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-17
  • 1970-01-01
相关资源
最近更新 更多