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

问题(阿里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。请设计一个高效算法实现这个需求。

 

下面,给出一种解法:

ExpandedBlockStart.gif 代码
#include  < stdio.h >

#define   LEN 20

int  path[LEN];
int  arr[LEN]  =  { 1 1 1 2 2 3 4 4 5 5 5 8 8 8 10 10 10 12 12 12 };

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相关),而且最大的问题在于,无法去掉重复的组合。求更好的解法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值