python 返回列表的递归函数

zd287kbt  于 2023-05-27  发布在  Python
关注(0)|答案(7)|浏览(160)

我想知道如何递归地实现第二个函数。

def sum(x):
    if x == 1:
        return 1
    else:
        return sum(x-1) + x
    
def factorials(x):
    list1 = []
    for c in range(1, x+1):
        list1.append(sum(c))
    return list1

print(factorials(10))

在第一个函数中,您将n作为参数传递,并返回1 + 2 + 3 + ...+ n
在第二个函数中,你将返回一个n个和的列表,例如当你调用factorial(10)时,输出将是[1,3,6,10,15,21,28,36,45,55]。
我真实的的问题是,我想知道是否有一些方法来做第二个功能,在一个递归的方式。我正在努力在递归函数中使用列表追加。

vs91vp4v

vs91vp4v1#

几个答案已经向您展示了如何通过调用自身和sum函数(也是误导性命名的)来让factorial函数(名称错误)生成一个列表。但是还没有人注意到重复调用sum(就像这个算法将要做的那样)是非常浪费的。您需要在factorial递归的每一级上递归一个sum调用链。
相反,您应该重写factorial,以直接根据列表中以前的值计算最新的值(递归查找)!这就是它的样子:

def factorial(n):
    """Returns a list of the first n triangular numbers"""
    if n <= 0:        # this base case is just for general safety
        return []
    if n == 1:        # this is the main base case, where our recursion ends
        return [1]

    lst = factorial(n-1)  # recurse, get a list back with n-1 values
    nth_value = lst[-1]+n # compute the nth value based on the (n-1)th value
    lst.append(nth_value) # add the value to the end of the list
    return lst

如果您 * 实际上 * 想要第一个n阶乘,而不是第一个n三角形数,请将lst[-1]+n替换为lst[-1]*n

5us2dqdw

5us2dqdw2#

首先是观察:不要将函数命名为sum,因为这是python中的内置函数。
解决方案是在递归函数的外部声明一个列表,你不需要sum或等效的函数:

def factorials(limit):
    def fact(limit, count: int, alist: list):
        if count > limit:
            return
        alist.append(1 if len(alist) == 0 else alist[-1] + count)
        fact(limit, count + 1, alist)

    list1 = []
    fact(limit, 1, list1)
    return list1

print(factorials(10))

生成[1, 3, 6, 10, 15, 21, 28, 36, 45, 55]。还要注意,这也是一个更python化的解决方案。

lymnna71

lymnna713#

正如@SimonUnderwood在评论中指出的那样,这是计算三角数,而不是阶乘。这就是说,这里有一些代码:

def triangulars(x):
    if x < 1:
        return []
    return triangulars(x - 1) + [sum(x)]

诀窍是在每次递归调用中向列表中追加一个项。在本例中,我使用sum为当前数字创建一个新列表,并使用列表上的加法运算符将其与其下数字的列表合并。

hgtggwj0

hgtggwj04#

因为你是在做累计求和(而不是实际的阶乘),你可以使用n(n+1)/2公式(或者你自己的sum()函数)来计算每一项:

def factorials(n): 
    return factorials(n-1) + [n*(n+1)//2] if n else []

def factorials(n): 
    return factorials(n-1) + [sum(n)] if n else []

或者,您可以将部分结果向下传递给递归,并在n达到零时将最终列表级联回返回堆栈。每个递归调用只需要使用最后一个值和当前长度来计算下一个要添加的条目:

def factorials(n,r=[0]): 
    return factorials(n-1,r+[r[-1]+len(r)]) if n else r[1:]

另一种方法是向下传递一个计数器,该计数器增加到n沿着最后一个结果值,并将递归列表与新条目连接起来(可以使用计数器向前计算):

def factorials(n,i=1,r=0): 
    return [] if i>n else [r+i]+factorials(n,i+1,r+i)
ewm0tg9j

ewm0tg9j5#

您可以使用scan实现triangle-

from operator import add

def triangle(x):
  return scan(add, 0, range(1, x + 1))

def scan(f, init, ls):
  if not ls:
    return [init]
  else:
    return [init] + scan(f, f(init, ls[0]), ls[1:])
print(triangle(10))
# [0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]

print(triangle(0))
# [0]
fcy6dtqo

fcy6dtqo6#

我修正了一些变量的命名以使其更清晰,并更改了一些条件,以便在x <= 0的情况下不会无限循环

def triangle(x):
    if x <= 1:
        return x
    else:
        return triangle(x-1) + x
    

# Although it doesn't impact this particular example, it's generally not recommended to use lists as default values. 
def get_triangular_sequence(x, found = None):
    if found is None:
        found = []
    if x <= 1:
        found.append(x)
        return found
    found.append(triangle(x))
    return get_triangular_sequence(x-1, found)

print(get_triangular_sequence(10))

这个列表将按照从大到小的顺序排列,但是如果你愿意的话,它可以很容易地翻转。

dced5bon

dced5bon7#

如果我没有在开头提到递归函数在Python中性能严重不足,那将是我的失职。在编写Python时,应该尽可能避免递归解决方案,因为迭代实现几乎总是更快更便宜。
递归函数调用自身,返回递归case或base case。基本情况最终将冒泡并结束递归,生成最终值。
例如,考虑这个递归定义的阶乘函数:

def factorial(n: int) -> int:
    if n == 0:
        return 1  # this should only be possible to reach
                  # on the first round of recursion, and
                  # is more of an early-out than a base case
    elif n == 1:
        # base case
        return n
    elif n < 0:
        raise ValueError("Factorial for negative number")
    else:
        # recursive case
        return n * factorial(n-1)

在处理了一些边缘情况(n=0,n<0)之后,你还剩下两种情况:

  • 基本情况:如果n == 1,停止递归并返回1
  • 递归情况:如果n >= 2,则将n乘以factorial(n-1)的下一个结果

如果你想要一个函数递归地计算其中的每一个,你可以做...

# from typing import List
def factorial_range(start: int, stop: int, _cur=None) -> List[int]:
    if start >= stop:
        raise ValueError('Invalid range')
    if _cur is None:
        _cur = start
    if _cur == stop:
        # base case
        return []
    else:
        # recursive case
        return [factorial(_cur)] + factorial_range(start, stop, _cur+1)

相关问题