【问题标题】:Cartesian product - using BackTracking - Python笛卡尔积 - 使用 BackTracking - Python
【发布时间】:2019-06-15 19:03:41
【问题描述】:

我正在练习解决递归和回溯练习。 我遇到了打印列表列表的所有笛卡尔积的问题,其中每个子列表仅包含不同的字符。当然,如果任何一个子列表为空 - 最终产品就是一个空列表。

我立即想到递归\回溯解决它。 我不擅长递归——人们给我的建议是: 将递归视为一个黑盒,只考虑一些适当的基本情况,并归纳假设您得到了 n-1 的答案,然后进行递归步骤。

所以这就是我的想法, “基本情况是什么?”当列表列表为空时 - 我将打印一个空列表。 如果不是,则返回第一个子列表的第一个字符,以及从下一个子列表对列表列表的递归调用。

def cartesian_product(lst):
    if len(lst)==0:
        return []
    for c in cartesian_product(lst[1:]):
        for s in c:
            return [lst[0][0]] + [s]

我想这里的问题是因为我不保存当前的子列表,我总是在第一个子列表中。 但是,有一个“NoneType”错误,我不知道为什么。

我如何知道何时需要函数助手?我什么时候可以按照人们告诉我的方式解决它?

【问题讨论】:

  • 也许你在同一个班? stackoverflow.com/a/54302988/633183
  • @user633183 哈哈。我不这么认为...我正在努力提高我的递归解决问题的能力,但不知道如何

标签: python python-3.x recursion backtracking


【解决方案1】:

首先,虽然这是递归,但我不认为它是回溯,因为我们不会组装然后可能会拒绝候选解决方案。我们在概念上将空列表视为我们的基本情况,但 Python 的循环逻辑不会使用空列表运行。因此,我们使用两种基本情况,一个空参数列表和一个仅包含单个子列表的参数列表。

如果我们的参数只有一个子列表[1, 2, 3],那么结果是[[1], [2], [3]],否则解决方案是将初始子列表的每个成员附加到递归调用我们自己的结果的前面(副本)在其余的子列表中:

def cartesian_product(array):
    product = []

    if array:  # avoid empty base case
        head, *tail = array

        if tail:  # not a base case
            for t in cartesian_product(tail):
                for h in head:
                    product.append([h] + t)
        else:  # one list base case
            product = [[h] for h in head]

    return product

此逻辑还为我们提供了所需的行为,即作为任何参数子列表出现的空列表会导致返回一个空列表作为结果。

【讨论】:

  • 你能解释一下*tail的用法吗?你能在这里为这个 * 提供一些替代方案吗?那么,我的问题是什么?实际上,我没有仔细考虑所有基本情况?谢谢。
  • @HelpMe,您标记了您的问题 [python-3.x],所以我使用了 Python 3 功能。 head, *tail = array 赋值将array 的第一个元素放入head,并将array 的其余部分放入tail。我猜相当于head, tail = array[0], array[1:]。
  • 好的,谢谢。你能解释一下我对递归的误解吗?我没有仔细考虑所有基本情况?
  • @HelpMe,我认为您的概念是正确的。如果我可以将所有单个列表项与空列表合并并且只有一个基本情况,我会更愿意而不是显式处理单个列表案例。但在将其映射到特定的编程语言时,这并没有奏效。
  • 如果我的概念是正确的,我真的不明白我的递归/代码有什么问题?
猜你喜欢
  • 1970-01-01
  • 2012-02-24
  • 2019-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-18
  • 2021-11-19
相关资源
最近更新 更多