我正在练习解决递归和回溯练习。 打印一个列表列表中的所有笛卡尔积时,我遇到了一个问题,其中每个子列表仅包含不同的字符。当然,如果其中一个子列表为空,则最终产品为空列表。
我立即想到了递归地\回溯地解决它。 我很不擅长递归-人们给我的建议是: 将递归视为一个黑盒,只考虑一些适当的基本情况,并归纳地假设您得到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”错误,我不知道为什么。
我如何知道何时需要功能助手?我什么时候可以解决我如何描述人们告诉我的?
答案 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
此逻辑还为我们提供了所需的行为,即空列表作为任何参数子列表出现都会导致结果返回空列表。