笛卡尔积-使用BackTracking-Python

时间:2019-01-22 10:22:19

标签: python python-3.x recursion backtracking

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

我立即想到了递归地\回溯地解决它。 我很不擅长递归-人们给我的建议是: 将递归视为一个黑盒,只考虑一些适当的基本情况,并归纳地假设您得到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”错误,我不知道为什么。

我如何知道何时需要功能助手?我什么时候可以解决我如何描述人们告诉我的?

1 个答案:

答案 0 :(得分:1)

首先,尽管这是递归,但我不认为它是 backtracking ,因为我们不会集合起来,然后可能拒绝一个候选解决方案。我们从概念上将空列表视为基本情况,但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

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