为啥我的递归会产生意外错误?以及如何在到达循环时修改递归?

Posted

技术标签:

【中文标题】为啥我的递归会产生意外错误?以及如何在到达循环时修改递归?【英文标题】:Why is my recursion producing an unexpected error? And how to amend the recursion when a loop has been reached?为什么我的递归会产生意外错误?以及如何在到达循环时修改递归? 【发布时间】:2021-06-24 01:25:54 【问题描述】:

我正在编写我认为是递归的代码,如下所示。代码的目的是取一些整数 n,并确定它是否是一个“快乐”的数字。一个“快乐”的数字是一个数字的平方和最终等于 1 的数字。

例如 19 是一个快乐的数字,因为 1^2 + 9^2 = 82 8^2 + 2^2 = 68 6^2 + 8^ 2 = 100 1^2 + 0^2 + 0^2 = 1.

n= 234
def square_sum(n):
    total_sum = 0
    for i in str(n):                
        square_char = int(i) **2    
        total_sum += square_char

return square_sum(n)

def loop_the_above(n):
    while n > 1:
         n = square_sum(n)

loop_the_above(n)

上面的“while n > 1”行出现错误;这是错误:

"TypeError: '>' not supported between instances of 'NoneType' and 'int' " ; why is this the case? 

另外,有人可以修改上面的代码吗,第一批运行良好,但我似乎无法让第二批(我相信递归)运行 - 我相信代码不太正确。 一旦达到相同的数字两次,我希望递归停止,因为这表明我们已经到达一个循环,并且该数字不再是一个“快乐”的数字,因为它永远不会达到 1。

【问题讨论】:

return square_sum(n) 这行是什么意思? 代码格式一定是错误的,因为你在函数外有一个return。在返回时,您再次调用square_sum,确实使用了递归,但这将永远循环,因为您没有递归的基本情况,也没有更改调用递归函数的arg。您可能应该致电square_sum(total_sum)(并添加基本情况)。 【参考方案1】:

确定一个数字是否是一个快乐的数字可能很困难,因为一个数字可能会陷入无休止的循环。例如20:

20 -> 4 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> ... and so on

您可以通过记住每个步骤的数字来跟踪周期。

递归方法

def is_happy_number(n: int, seen=[]) -> bool:
    if n == 1:
        return True
    square_sum = sum(int(digit) ** 2 for digit in str(n))
    if square_sum in seen:
        return False
    seen.append(square_sum)
    return is_happy_number(square_sum, seen)


print(is_happy_number(19))  # True
print(is_happy_number(20))  # False
print(is_happy_number(201231123))  # False

迭代方法

递归没那么性感,让我们摆脱它:

def is_happy_number2(n: int) -> bool:
    seen = set()
    while n != 1 and n not in seen:
        seen.add(n)
        n = sum(int(digit) ** 2 for digit in str(n))
    return n == 1

等空间法

唯一满意的一位数字是17。让我们考虑到这一点。

def is_happy_number(n: int) -> bool:
    while n > 9:
        n = sum(int(digit) ** 2 for digit in str(n))

    return n in (1, 7)

【讨论】:

seen 最好实现为 set 以实现更快的 O(1) 测试。 优秀的评论@Booboo,我在迭代方法中考虑到了这一点

以上是关于为啥我的递归会产生意外错误?以及如何在到达循环时修改递归?的主要内容,如果未能解决你的问题,请参考以下文章

iOS 为啥我的 UIPickerview 方法在循环?

为啥我的输出在到达这部分代码时会冻结?

为啥我的 N Queens 算法会到达最后一行?

如何再次重用声音以及为啥我的声音在到达预期页面之前离开了一页?

为啥意外的无限循环会增加 CPU 使用率?

为啥这个回调会产生无限循环