分别存储阵列的每个子集的总和而不是所有子集的总和

时间:2016-04-04 06:21:03

标签: c algorithm recursion subset

我有一个数组a [] = {1,2,3},我想要这些元素的所有可能组合的单独总和,即; O(n)复杂度中1,2,3,1 + 2,1 + 3,2 + 3,1 + 2 + 3(不是所有子集的总和),数组甚至可以有3个以上的元素

#include <stdio.h>
#include <stdlib.h>


int timewaste(int a[],int i,int sum,int l)
{
    sum= sum + a[i];
    printf("%d\n\n",sum);
    if(i==0)
    {
        return 1;
    }
    for(i=i-1;i>=0;i--)
    {
        timewaste(a,i,sum,l);
    }
    return 1;
}

int main()
{
    int i,n,a[50],y,t,pehlibaar;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(i=n-1;i>=0;--i)
    {
        pehlibaar=0;
        timewaste(a,i,pehlibaar,1);
    }
    return 0;
}

以下是我尝试使用递归http://uploadpie.com/dQpQp

的图表中的图像链接

2 个答案:

答案 0 :(得分:0)

将此行for(i=i-1;i>=l;i--)更改为for(i=i-1;i>=0;i--)

答案 1 :(得分:0)

我想说,因为有2^n个不同的子阵列,你可能在最坏的情况下有2^n个不同的总和(这种情况发生在元素足够远的时候) - 并且你想要存储所有他们是明确的。因此无法在线性时间内解决问题;这是因为你必须触摸&#34;每个2^n总和,以便存储它们;这意味着您必须至少进行2^n次操作才能访问所有金额。最坏的情况下需要O(2^n)次。 (更确切地说,我们在运行时间上有Omega(2^n)下限。)

就算法而言,为什么不从总和开始然后继续减去。这是算法的伪代码。

array = {1, 2, ..., 3} // array of size n
subtracted = {false, false, ..., false}
sum = array[0]+array[1]+...+array[n-1]
visitedArray= {} // hashtable that tels whether we've visited a given array
void all_sums(array, subtracted, sum) {
     // If we've already seen the array, do nothing
     if (visitedArray[array]) return;
     // otherwise, process it
     print sum
     // Remember that we've visited the array, so we don't repeat unnecessary work         
     visitedArray[array] = true;
    // process the current sum---e.g. store wherever you want
    for (i = 0; i < n; ++i) {
        if (!subtracted[i]) {
            subtracted[i] = true;
            all_sums(array, subtracted, sum-array[i])
            subtracted[i] = false;
        }
    }
}

我使用visiedArray的原因是为了避免以不同的方式计算相同的总和,例如我们通过先减去3然后再减去2和1得到的1首先减去2然后减去3.(如果不删除这些,则运行时间变为O(n! * 2^n)。)