一道算法题,求更好的解法

问题(阿里2010年实习):

 给定一个数t,以及n个整数,在这n个整数中找到相加之和为t的所有组合,例如t = 4n = 6,这6个数为[4, 3, 2, 2, 1, 1],这样输出就有4个不同的组合,它们的相加之和为44, 3+1, 2+2, and 2+1+1。请设计一个高效算法实现这个需求。

 

下面,给出一种解法:

代码
#include <stdio.h>

#define  LEN 20

int path[LEN];
int arr[LEN] = {11122344555888101010121212};

void clearpath()
{
    
int i;
    
for (i = 0; i < LEN; i++)
    {
        path[i] 
= 0;
    }
}
void out_put()
{
    
int i;
    
for (i = LEN-1; i >= 0; i--)
    {
        
if(path[i] == 1)
            printf(
" %d ", arr[i]);
    }
    printf(
"\n");
}

/*算法:
**q(n, t)表示从arr[0]...arr[n]中选出和为t的子集,则
**q(n, t) = q(n-1, t-arr[n]) + q(n-1, t)
*/
void q(int n, int t, int flag)
{
     
if(t < 0)
         
return;

    path[n
+1= flag;

    
if(n == 0)
    {
        
if(t == 0)
        {
            path[n] 
= 0//不包含arr[0]
            out_put();
        }
        
else if(arr[n] == t)
        {
            path[n] 
= 1;//包含arr[0]
            out_put();
        }
    }
    
else
    {
        q(n
-1, t-arr[n], 1); //包含arr[n]
        q(n-1, t, 0); //不包含arr[n]
    }
}

void subsum(int len, int t)
{
    q(len 
- 1, t - arr[len], 1);
    q(len 
- 1, t, 0);
}
int main()
{
    
int t = 20;
    clearpath();
    subsum(LEN 
- 1, t);
    
return 0;
}

 

该算法的时间复杂度为指数级(但实际情况应该好很多,与t相关),而且最大的问题在于,无法去掉重复的组合。求更好的解法。

posted @ 2010-05-14 21:19  YY哥  阅读(3887)  评论(18编辑  收藏  举报