笛卡尔积-使用回溯-Python

笛卡尔积-使用回溯-Python,python,python-3.x,recursion,backtracking,Python,Python 3.x,Recursion,Backtracking,我正在练习解决递归和回溯练习。 我遇到了一个打印列表的所有笛卡尔乘积的问题,其中每个子列表只包含不同的字符。当然,如果子列表中的任何一个子列表为空,则最终产品为空列表 我立即想到递归\回溯地解决它。 我不擅长递归——人们给我的建议是: 将递归视为一个黑盒,只考虑一些适当的基本情况,并假设归纳式地给出了n-1的答案,然后进行递归步骤 这就是我的想法, “基本情况是什么?”当列表为空时,我将打印一个空列表。 如果不是,则返回第一个子列表的第一个字符,再加上下一个子列表对列表的递归调用 def car

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

我立即想到递归\回溯地解决它。 我不擅长递归——人们给我的建议是: 将递归视为一个黑盒,只考虑一些适当的基本情况,并假设归纳式地给出了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]
我想这里的问题是因为我不保存当前子列表,我总是在第一个子列表。 但是,有一个“非类型”错误,我不知道为什么

我如何知道何时需要函数助手?我什么时候能解决我描述的人们告诉我的问题?

首先,虽然这是递归,但我不认为它会回溯,因为我们不打算组装,然后可能拒绝,一个候选解决方案。从概念上讲,我们认为空列表是基本情况,但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
。相当于头,尾=数组[0],数组[1://我猜。好的,谢谢。你能解释一下我对递归的误解吗?我没有仔细考虑所有的基本情况?@HelpMe,我认为你的想法是正确的。与其显式地处理单个列表的情况,不如将所有单个列表项与空列表合并,并且只有一个基本情况。但是当把它映射到一种特定的编程语言上时,这并没有起作用。如果我的概念是正确的,我真的不明白递归/代码的问题是什么?也许你在同一个类中@用户633183哈哈。我不这么认为。。。我正在努力提高我解决递归问题的能力,但不知道如何提高