子集生成算法的时间复杂度

时间:2018-08-19 04:42:17

标签: python algorithm time-complexity complexity-theory

以下代码的算法复杂度为O(2 ^ n)

def genSubsets(L):
    res = []
    if len(L) == 0:
        return [[]]
    smaller = genSubsets(L[:-1]) # find all subsets without last element
    extra = L[-1:] # create a list of just last element
    new = []
    for small in smaller:
        new.append(small+extra) # for all smaller solutions, add one with last element
    return smaller + new # combine those with last element and those without

# Given explanation: For a list of size n there are 2^n cases ---> O(2^n) <huh?>

我不知道长度为n的列表有2 ^ n种情况。

这是我的理解:

  • 长度为n的列表将进行n次递归调用(每个调用在没有最后一个元素的列表中传递->进行直到空列表[]为止)。这是O(n)的复杂性
  • 然后您开始逐步进行递归调用
  • 随着向上移动,已解决子问题(“较小”列表)的数量增加,因此每次递归调用中完成的循环次数都会增加
  • “较小”的列表大小(从最深的递归调用开始):0、1、2、4、8、16 ...
  • 操作总数0 + 1 + 2 + 4 + ... 2 ^ n(因为存在n个递归)
  • O(2 ^ n)

这种解释有意义吗? (大声笑,我在写这篇文章时回答了我的问题,但是一些外部知识对XD很有帮助)

1 个答案:

答案 0 :(得分:0)

  

我不知道长度为n的列表有2 ^ n种情况。

  • 好,在这种情况下,要检查每个可能的子集,我们在迭代中take the current element,或者在迭代中don't take current element

  • 这为我们每个元素带来2种情况->接受或不接受。

    对于下面的树,我将take表示为T,将Don't take表示为DT

让我们考虑这个数组=> [1,3,5]。 递归树看起来像这样-

                               Start state
                               /          \
                              /            \
                             /              \
                          T-1                DT-1
                         /   \               /   \
                        /     \             /     \
                       /       \           /       \
                      /         \         /         \
                     T-3      DT-3      T-3         DT-3
                    / \        /  \      / \         /  \
                   /   \      /    \    /   \       /    \
                  T-5  DT-5 T-5  DT-5  T-5  DT-5   T-5   DT-5
  • 从上面的树中可以看到,有 2 3 个叶子定义了 2 3 个子集可能性< / strong>。您可以为大于3的输入创建此类递归树,以了解在这种情况下为什么复杂度是指数级( 2 n )。

  • 您可以通过从根遍历到每个叶子来检测此树中的任何子集。

    例如-[Start state,T-1,DT-3,T-5]表示子集[1,5]