从包含有M个数的集合中中取出不大于N个的数(可重复取)相加,求所有可能的和的集合

Heray 2007-05-18 11:31:00
比如数集{1,2,4},N = 2
则可能的和的集合是{1,2,3,4,5,6}
不知道算法复杂度是否能控制到O(MN)
...全文
359 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
fire_woods 2007-05-22
  • 打赏
  • 举报
回复
楼上的证明巧妙.
medie2005 2007-05-22
  • 打赏
  • 举报
回复
对于N值很大的情况,我给的那个代码效率就很低了。

但是,对于N值很大的情况,实际上,并没有什么研究意义了。

因为,若N值很大,令Min,Max分别等于数集中的最小和最大元素值。那么按约束条件形成的集合极有可能包含[Min,Max*N]的绝大部分数,这实际上是没什么意义的。

因此,如果出现了N值很大的情况,可以依次对[Min,Max*N]中的数遍历,判断是否可以写成满足约束条件的形式。
tailzhou 2007-05-22
  • 打赏
  • 举报
回复
"不知道算法复杂度是否能控制到O(MN)"

假设数集为{1,2,4,8,16,32,64....2^m},
则不管N为多少,可能的和的个数大于(可重复取)或等于(不能重复取)C(m,n),达不到O(MN);





tailzhou 2007-05-22
  • 打赏
  • 举报
回复
lz描述不清:
“从包含有M个数的集合中中取出不大于N个的数(可重复取)相加,求所有可能的和的集合 ”;

“比如数集{1,2,4},N = 2
则可能的和的集合是{1,2,3,4,5,6}”

既然可以重复取
那么取2个4应该包含有8呀;
medie2005 2007-05-21
  • 打赏
  • 举报
回复
效率不太高的代码:

/****************************************
* 数字组合问题
*
*
* 2007-5-21
******************************************/

#include <iostream>
#include <vector>

using namespace std;

int main( )
{
int M;
cout<<"请输入数集的大小M:";
cin>>M;
int *element=new int[M];
int i=0,Max=0;
cout<<"请输入数集的元素:";
while(i<M)
cin>>element[i++];

for( i=0; i<M; ++i )
if( element[i]>Max )
Max=element[i];
int N;
cout<<"请输入每个元素最大的重复次数N:";
cin>>N;
vector<int> *list=new vector<int> [N+1];

int len=Max*N+1;
int *hash=new int[len];
i=0;
while(i<len)
hash[i++]=0;

int j, k, temp, mid;
vector<int>::iterator iter, end;
for( i=0; i<M; ++i )
{
list[1].push_back(element[i]);
hash[element[i]]=1;
}
for( i=0; i<M; ++i )
{
for( j=1; j<=N; ++j )
{
mid=j*element[i];
for( k=0; k<=N-j; ++k )
{
iter=list[k].begin();
end=list[k].end();
while(iter!=end)
{
temp=*iter+mid;
if( hash[temp]==0 )
{
hash[temp]=1;
list[k+j].push_back(temp);
}
++iter;
}
}
}
}
cout<<"{";
for( i=0; i<len-1; ++i )
if( hash[i]==1 )
cout<<i<<",";
cout<<len-1<<"}"<<endl;

delete []hash;
delete []list;
delete []element;

return 1;
}
chiyq118 2007-05-19
  • 打赏
  • 举报
回复
mark
flyingdog 2007-05-19
  • 打赏
  • 举报
回复
去重复没怎么复杂吧。
使用hash或者平衡树都可以在插入的时候判断是否有重复,有重复就不插入了。
Heray 2007-05-19
  • 打赏
  • 举报
回复
按照flyingdog的做法,每加一次数据个数就要番N倍,而且加的结果大多是重复的,这样算法复杂度应该是O(M^N * N),除非可以在每次计算时将重复的结果去掉。
Heray 2007-05-19
  • 打赏
  • 举报
回复
很有兴趣,请告知具体算法,有分相赠,谢谢
medie2005 2007-05-19
  • 打赏
  • 举报
回复
可以做到复杂度为 O(Max*N^3*M) (Max=数集中的最大元素)。
Heray 2007-05-18
  • 打赏
  • 举报
回复
这种做法复杂度应该是O(M*M*N)吧?
做完过后还需要将结果中重复的数去掉
flyingdog 2007-05-18
  • 打赏
  • 举报
回复
首先初始化某个集合为空。然后共遍历N次,每次对于集合中的某个元素加上M中的某个值,放入新的集合中。当然集合中的元素需要做到不重复。

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧