为什么powerset给出2 ^ N时间复杂度?

时间:2014-07-04 15:12:38

标签: math recursion discrete-mathematics recurrence

以下是用于生成powerset的递归函数

void powerset(int[] items, int s, Stack<Integer> res) {
     System.out.println(res);

     for(int i = s; i < items.length; i++) {
          res.push(items[i]);
          powerset(items, s+1, res);
          res.pop();
     }
}

我真的不明白为什么会这样做O(2^N)2来自何处? 为什么T(N) = T(N-1) + T(N-2) + T(N-3) + .... + T(1) + T(0)解决了O(2^n)。有人可以解释为什么吗?

5 个答案:

答案 0 :(得分:3)

每当我们决定将另一个元素添加到原始数组时,我们将执行的操作数量增加一倍。

例如,假设我们只有空集{}。如果我们想添加{a},电源设置会发生什么?然后我们将有2套:{},{a}。如果我们想添加{b}怎么办?然后我们会有4套:{},{a},{b},{ab}。

注意2 ^ n也意味着倍增性质。 2 ^ 1 = 2,2 ^ 2 = 4,2 ^ 3 = 8,......

答案 1 :(得分:3)

以下是更一般的解释。 请注意,生成功率集基本上是生成组合。 (nCr是可以通过从n个项目中获取r个项目来进行组合的数量)

formula: nCr = n!/((n-r)! * r!)

示例:{1,2,3}的权力集为{{},{1},{2},{3},{1,2},{2,3},{1,3} { 1,2,3}} = 8 = 2 ^ 3

1) 3C0 = #combinations possible taking 0 items from 3 = 3! / ((3-0)! * 0!) = 1
2) 3C1 = #combinations possible taking 1 items from 3 = 3! / ((3-1)! * 1!) = 3
3) 3C2 = #combinations possible taking 2 items from 3 = 3! / ((3-2)! * 2!) = 3
4) 3C3 = #combinations possible taking 3 items from 3 = 3! / ((3-3)! * 3!) = 1

如果你加上4,它出来1 + 3 + 3 + 1 = 8 = 2 ^ 3。所以基本上它在n个项目的幂集中被证明是2 ^ n个可能的集合。

因此,在算法中,如果要生成具有所有这些组合的幂集,那么它将花费与2 ^ n成比例的时间。所以时间复杂度是2 ^ n。

答案 2 :(得分:2)

像这样的东西

T(1)= T(0);

T(2)= T(1)+ T(0)= 2T(0);

T(3)= T(2)+ T(1)+ T(0)= 2T(2);

因此我们有

T(N)= 2T(N-1)= 4T(N-2)= ...... = 2 ^(N-1)T(1),其为O(2 ^ N)

答案 3 :(得分:1)

我可以用几种数学方法向你解释第一个:

考虑像a这样的一个元素,每个子集都有2个关于a的选项,或者他们有没有,所以我们必须有$ 2^n $子集,因为你需要调用函数来创建每个子集你需要调用这个函数$ 2^n $

另一种解决方案:

这个解决方案是通过这个递归产生你的方程,让我先定义T(0) = 2,首先用一个元素定义一个元素,我们有T(1)= 2,你只需要调用函数,它就在这里结束。现在假设对于每个具有k < n元素的集合,我们都有这个公式

  

T(k)= T(k-1)+ T(k-2)+ ... + T(1)+ T(0)(我将其命名为*公式)

我想证明,对于k = n,这个等式是正确的。

考虑具有第一个元素的每个子集(就像你在算法开始时所做的那样,并推送第一个元素)现在我们有n-1个元素,所以需要T(n-1)来查找具有第一个元素的每个子集元件。到目前为止我们有:

  

T(n)= T(n-1)+ T(没有第一个元素的子集)(我将其命名为**公式)

在你的for循环结束时你移除了第一个元素现在我们有了每个没有第一个元素的子集,就像我在(**)中所说的那样,你再次拥有n-1个元素,所以我们有:

  

T(没有第一个元素的子集)= T(n-1)(我将它命名为 * 公式)

来自公式(*)和( * )我们有:

  

T(没有第一个元素的子集)= T(n-1)= T(n-2)+ ... + T(1)+ T(0)(我将它命名为****公式)

现在我们拥有你想要的第一个,从公式()和(** )我们有:

  

T(n)= T(n-1)+ T(n-2)+ ... + T(1)+ T(0)

我们还有T(n) = T(n-1) + T(n-1) = 2 * T(n-1)所以T(n) = $2^n $

答案 4 :(得分:1)

Shriganesh Shintre的答案非常好,但您可以进一步简化它:

假设我们有一套 S

Oscar

现在我们可以写一个子集 s ,其中集合中的每个项目可以具有值1(包括)或0(排除)。现在我们可以看到可能的集合 s 的数量是以下产品:

{a1, a2, ..., aN}2 * 2 * ... * 2