如何提出回溯问题的时间复杂度?

时间:2019-08-06 05:44:01

标签: python time-complexity backtracking

给出列表列表,打印列表列表,其中输出中的每个列表都是输入列表中元素的组合。

例如: I / P-> [[''a','b'],['c'],['d','e','f']]

o / p-> ['a','c','d'],['a','c','e'],['a','c','f'], ['b','c','d'],['b','c','e'],['b','c','f']

我想出了回溯解决方案。下面是代码。但是,我很难找到它的时间复杂度。我认为这是O(m ^ n),其中m是给定列表中最长列表的长度,n是给定列表中长度的。这样对吗?如何找到此类回溯问题的时间复杂性?

def helper(lists, low, high, temp):
    if len(temp) == high:
        print temp
    for i in range(low, high):
        for j in range(len(lists[i])):
            helper(lists, i+1, high, temp+[lists[i][j]])

if __name__ == "__main__":
    l = [['a','b'],['c'],['d','e','f']]
    helper(l, 0, len(l), [])

2 个答案:

答案 0 :(得分:2)

关于复杂性问题:

如果有K个列表,每个列表的长度为n_k,对于k = 1,...,K,则您需要输出的列表总数为n_1 * n_2 * ... * n_K(假设顺序无关紧要) 。当您n_1 = n_2 = ... = n_k时,边界一定很清楚并且很锐利。

或者,我们可以让N = n_1 + ... + n_k为输入列表的不相交并集的大小,并根据N寻找界限。对于固定的N,最坏的情况发生在n_1 == n_2等处,我们得到O((N/k)^k)。在k上最大化,我们发现k=N/e其中e的欧拉数。因此,我们有O(e^(1/e)^N) ~ O(1.44^N)

正如LeopardShark所建议的那样,您可以查找产品的itertools实现以供参考。它不会提高渐近速度,但是由于懒惰的回报,它将提高空间利用率。

更整洁的Python实现如下:

def custom_product(lsts):
    buf = [[]]
    for lst in lsts:
        buf = [b + [x] for b in buf for x in lst]
    return buf

答案 1 :(得分:0)

您实际上正在做的是重新实现itertools.product()

您上面的代码等同于

import itertools

if __name__ == "__main__":
    l = [['a','b'],['c'],['d','e','f']]
    l2 = itertools.product(*l)
    for x in l2:
        print(list(x))

我认为这两个解决方案的时间复杂度均为O(列表数量×列表长度的乘积),但是itertools.product()会更快,用C编写并经过适当优化。