【问题标题】:How to come up with time complexity of backtracking problem?如何提出回溯问题的时间复杂度?
【发布时间】:2019-08-06 05:44:01
【问题描述】:

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

例如: 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), [])

【问题讨论】:

    标签: python time-complexity backtracking


    【解决方案1】:

    关于复杂性问题:

    如果有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
    

    【讨论】:

      【解决方案2】:

      您实际上正在做的是重新实现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 语言编写并经过适当优化。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-21
        • 1970-01-01
        • 1970-01-01
        • 2021-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多