双递归,仅使用特定数字查找最小倍数

时间:2017-01-24 19:22:32

标签: python algorithm recursion

这是我的问题源于(来自Hackerrank)的问题陈述:给定一个整数N.你能找到由最小值为9和0组成的最小正整数X.这样,X是N的倍数? X由一个或多个出现的9和零个或多个出现的0组成。

我以为我会使用双递归,但我无法理解如何使其工作。我的函数接收" multiple",这是一个字符串(这样我可以在其他函数调用中附加' 0'或' 9'而不是处理算术)和"除数"。

基本上我想继续调用我的函数,将9或0添加到"多个"在每次通话时,返回最终的"倍数"当它最终被" divisor"整除时。我设想它是一个函数调用树,每次在函数(多个' 9',除数)和函数(多个+' 0',除数)之间分割。

然而,似乎一旦我调用return,它就没有进入第二个函数调用:

#multiple is a string
def rec_nine_zero(multiple, divisor):
    if int(multiple) % divisor == 0:
        return multiple
    else:
        return rec_nine_zero(multiple + '9', divisor)
        return rec_nine_zero(multiple + '0', divisor)

以下作品:

print(rec_nine_zero('9', 1111))

但是,如果我尝试这个(所需的倍数是90):

print(rec_nine_zero('9', 5)
它崩溃并告诉我基本上堆栈爆炸,这意味着它永远不会进入第二个函数调用。

我能看到的一个问题是,即使我设法让return语句调用这两个函数(多个+' 9'以及多个+' 0'),我觉得就像函数调用树的所有分支一样,除了一个(最终找到正确结果的那个)之外,它将继续运行,直到堆栈显示" annnnd ...我们已经完成"。

编辑:根据Prune的回答,这是我的新功能:

def rec_nine_zero(multiples, divisor):
    for multiple in multiples:
        if int(multiple) % divisor == 0:
            return multiple
    new_multiples = []
    for multiple in multiples:
        new_multiples.append(multiple + '0')
        new_multiples.append(multiple + '9')
    return rec_nine_zero(new_multiples, divisor)

2 个答案:

答案 0 :(得分:3)

它爆炸了,因为你已经以深度优先搜索的规范方式完成了这项工作。只要需要找到解决方案,您可以在9&#39的字符串中尝试第一个分支。由于N = 5没有任何此类解决方案,因此在重新打击堆栈之前会重复使用。

转换为广度优先。生成并测试最小的字符串,' 9'。如果失败,请重复您想要扩展的字符串列表:[" 9"]。

在递归中,您追加' 0' 0和' 9'列表中的每个候选人。在第一次递归时,这会给你[" 90"," 99"]。当N = 5时,您将在此阶段返回成功。如果您有其他一些号码,例如7号,那么您将重新使用此新列表。

在下一步,您将测试列表[" 900"," 909"," 990"," 999&# 34;],并继续这个过程,直到你成功。

顺便说一下,如果你退出string和int之间的转换,你可以更容易:只需要从9开始。下一个阶段将对前一个列表中的每个x的10 * x和10 * x + 9工作。

这会让你感动吗?

答案 1 :(得分:2)

不是答案,而是另一种更简单的方法来解决问题 -

def rec_nine_zero(divisor):
    d = divisor
    while True:
        if all([True if i in '09' else False for i in `d`]): return d 
        else: d+=divisor

print rec_nine_zero(111)    

无论如何要回答你的问题 -

您的代码中有一些警告可能会为您提供有关递归的一些提示。

  • 首先,在同一个构造中的另一个return语句下有一个return语句,因此第二个return语句永远不会运行。
  • 第二件事是你错过了递归的基本情况,这是阻止递归继续进行所必需的。你的代码现在正在做的只是追加9和9和9 ......,你的第一个案例是有效的,因为幸运的是,111有999的倍数。在其他情况下,它失败了。

不幸的是,如果你以这种方式解决这个问题,你就无法构建这个问题的基础案例。 @Prune给出的解决方案是正确的。

希望它有所帮助!

是的,你做对了!无论如何,我喜欢缩短代码,所以在这里你使用规范的bfs-

def rec_nine_zero(multiples, divisor):
    que = [];que.append('9')
    while(len(que) != 0):
        k = que.pop()
        if int(k)%divisor == 0:return k
        que.append(k+'9');que.append(k+'0')
    return -1   

print rec_nine_zero('9', 5)    

PS - 我相信它可以缩短更多!