【问题标题】:Creating a nested recursive list without slicing创建没有切片的嵌套递归列表
【发布时间】:2022-01-05 04:22:55
【问题描述】:

我需要编写一个接收非负整数并返回的函数:

[] for n=0 

[[]] for n=1 

[[],[[]]] for n=2

[[],[[]],[[],[[]]]] for n=3

等等。对于n,我们将收到一个n 大小的列表,因此在索引i 中将包含列表中的所有i-1 元素。我不知道如何更好地解释这一点,英语不是我的第一语言。

我不允许使用列表切片或循环,我应该在没有 copy 模块的情况下创建每个列表的深层副本。我不允许让 2 个不同的列表或索引指向内存中的同一个列表。

这是我尝试过的:

def list_seq(x, outer_list=[]):
    if x == 0:
        return []
    outer_list.append(list_seq(x-1,outer_list))
    return outer_list

print(list_seq(2)) 的输出是[[], [...]]

【问题讨论】:

  • “我想创建每个列表的深层副本”这是否意味着您不应该缓存递归调用的结果?在这种情况下,将具有非常高复杂性。
  • @tobias_k 我不允许 2 个不同的列表或索引指向内存中的同一个列表
  • 你尝试了什么?
  • @PApostol 更新了帖子
  • @MadaBit 你为什么回滚你的代码尝试?没有它,这个问题就跑题了。

标签: python list recursion


【解决方案1】:

如果你不能使用循环,你可以使用以下:

def recursive_list(n):
    if n == 0:
        return []
    else:
        return recursive_list(n-1) +  [recursive_list(n-1)]

编辑

如果您想使用append,您可以执行以下操作:

def recursive_list(n: int) -> list:
    if n:
        result = recursive_list(n-1)
        result.append(recursive_list(n-1))
        return result
    return []

注意正如 cmets 中指出的,caching 引入了一些参考问题,因此我删除了缓存版本。

【讨论】:

  • 这是一个很好的解决方案。非常感谢。是否可以使用附加方法而不是+?也许有一个辅助函数
  • 添加了append的解决方案。
  • 使用functools.cache 破坏了进行两次递归调用而不是一次的整个目的。考虑:l = recursive_list(4); print(l)[[], [[]], [[], [[]]], [[], [[]], [[], [[]]]]]; l[1].append('oops'); print(l); [[], [[], 'oops'], [[], [[], 'oops']], [[], [[], 'oops'], [[], [[], 'oops']]]]
  • @Stef fair。我只是确保列表不是独立的。我没有考虑 OP 是否计划附加到中间的列表中,这是我的疏忽。考虑到 OP 不能使用切片、复制或循环,不确定结果是否可以被缓存。即使有一些自定义缓存功能,也需要一些机制来复制列表。
【解决方案2】:

您可以使用简单的列表推导将其写成递归函数:

def f(n):
    return [f(i) for i in range(n)]

或者,您也可以使用map

def f(n):
    return list(map(f, range(n)))

但请注意,如果没有 caching,这将变得相当缓慢。

【讨论】:

  • 对不起。忘了说我不能使用循环
  • @MadaBit return [*map(f, range(n))] 那么呢?
【解决方案3】:

另一种较短的递归解决方案,没有循环:

def l_list(n):
  def f(c, d = []):
     return d if c == n else f(c+1, d+[l_list(c)])
  return f(0)

print(l_list(0))
print(l_list(1))
print(l_list(2))
print(l_list(3))

输出:

[]
[[]]
[[], [[]]]
[[], [[]], [[], [[]]]]

【讨论】:

    【解决方案4】:

    只是另一个想法,我认为它满足所有规则/要求:

    def f(n):
        a = []
        exec('a.append(1 * a);' * n)
        return eval(repr(a))
    

    演示用法:

    for n in range(5):
        print(f(n))
    

    输出:

    []
    [[]]
    [[], [[]]]
    [[], [[]], [[], [[]]]]
    [[], [[]], [[], [[]]], [[], [[]], [[], [[]]]]]
    

    【讨论】:

    • 不错的想法,但可怕的实现。为什么不只是for _ in range(n): a.append(list(a)),然后是return a
    • @tobias_k 因为问题是“我不允许使用列表切片或循环”。
    • @tobias_k 还因为它“我不允许让 2 个不同的列表或索引指向内存中的同一个列表”。
    • @tobias_k It doesn't
    猜你喜欢
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    • 2021-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多