您的位置:首页 > 其它

[经典算法] 排列组合-N元素集合的M元素子集

2015-09-25 11:41 615 查看

题目说明:

假设有个集合拥有n个元素,任意的从集合中取出m个元素,则这m个元素所形成的可能子集有那些?

题目解析:

假设有5个元素的集合,取出3个元素的可能子集如下:{123}、{124}、{125}、{134}、{135}、{145}、{234}、{235}、{245}、{345}这些子集已经使用字典顺序排列,如此才可以观察出一些规则:如果最右一个元素小于m,则如上面一样的不断加1如果右边一位已至最大值,则加1的位置往左移每次加1的位置往左移后,必须重新调整右边的元素为递减顺序

所以关键点就在于哪一个位置必须进行加1的动作,到底是最右一个位置要加1?还是其它的位置?
在实际撰写程式时,可以使用一个变数positon来记录加1的位置,position的初值设定为n-1,因为我们要使用队列,而最右边的索引值为最大的n-1,在position位置的值若小于m就不断加1,如果等于m了,position就减1,也就是往左移一个位置;由于位置左移后,右边的元素会经过调整,所以我们必须检查最右边的元素是否小于m,如果是,则position调整回n-1,如果不是,则positon维持不变。

程序代码:

#include<gtest/gtest.h>
usingnamespacestd;

voidShowResult(intdata[],intM)
{
for(inti=0;i<M;i++)
{
cout<<data[i]<<"";
}
cout<<endl;
}

intGenerateMFromN(intN,intM)
{
intnCount=0;
if(M==0)
{
return1;
}

int*State=newint[M];
for(inti=0;i<M;i++)
{
State[i]=i+1;
}

nCount++;
ShowResult(State,M);

intnPos=M-1;

while(State[0]<N-M+1)
{
if(State[M-1]==N)
{
nPos--;
}
else
{
nPos=M-1;
}

State[nPos]++;

for(inti=nPos+1;i<M;i++)
{
State[i]=State[i-1]+1;
}

ShowResult(State,M);
nCount++;
}

delete[]State;

returnnCount;
}

TEST(Algo,tGenerateMFromN)
{
//3选0组合3!/(0!*(3)!)=1
ASSERT_EQ(GenerateMFromN(3,0),1);

//5选3组合5!/(3!*(5-3)!)=10
ASSERT_EQ(GenerateMFromN(5,3),10);

//5选5组合5!/(5!*8!)=1
ASSERT_EQ(GenerateMFromN(5,5),1);

//10选2组合10!/(2!*8!)=45
ASSERT_EQ(GenerateMFromN(10,2),45);
}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: