||
有n个不同球,从中选择m个,不考虑选择的顺序,可以列出多少种选择?这问题是简单的,若n阶乘表示为:fact(n),且把问题记作C(n,m)。那么:C(n,m) = fact(m)/fact(n)/fact(n-m) 。当用程序直接列出所有可选,虽然不难,可以直接想到排列加剔除的方式,然而这样的程序显然是非常的丑陋的。应该得有好点的算法去解决它:对球编号1:n,问题等价从1:n中选择m个不同的数字。假设C(n,m-1)的排列已知,则每一种排列{a,b,c,…x}衍生C(n,m)的排列{a,b,c…x,y},其中y为(x+1):n中的任意,共衍生排列n-x项。注:要求每列的数字顺序为增序,即a<b<c…。
MATLAB程序描述:
function re=getspre(n,m)
re=(1:n)';
while(size(re,2)<m)
tmp=[];
for i=1:size(re,1)
tmp=[tmp;[ones(n-re(i,end),1)*re(i,:),(re(i,end)+1:n)']];
end
re=tmp;
end
end
>> getspre(5,3)
ans =
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
算法要求每个排列是单调递增序列,则令所有选择无重复,对于任意可能出现在C(n,m)的序列必然有C(n,m-1)的源所以选择没有遗漏。算法结构描述排列数量是以如下方式增长的:,共有求和号m-1个。
例: 。
另,对于问题:有n个编号不同的球,可以有多少种不同的顺序排列方式?记为P(n)。那么列出P(n)的全部排列可以有很多种方式列出,但程序的结构应力求用更少的时间复杂度,以及更少的内存资源。下面是一个方式,用MATLAB描述:
function H=sepn(n)
if(n==1)
H=1;
return;
end
regu=sepn(n-1);
H=[];
x=[1:n,1:n];
for i=2:n
tx=x(i:i+n-2);
H=[tx(regu);H];
end
H=[regu;H];
L=reshape(ones(size(regu,1),1)*(n:-1:1),[],1);
H=[H,L];
end
>> sepn(3)
ans =
1 2 3
2 1 3
3 1 2
1 3 2
2 3 1
3 2 1
假设P(n-1)的排列已知,序列T={1,2,…n,1,2,…n},那么做序列Xi={T(i),T(i+1),T(i+2)…T(i+n-2)},其中i=1:n。对所有Xi序列进行P(n-1)排列,所有得到的序列末位最后补上T(i+n-1)。算法不需要任何多余的判断和剔除,而且存储结构上也不需要多余的资源,最后的到的数组所有位在整个过程中都只赋值一次。方式用C++或者JAVA来做会看到更简易结构:
package amk2;
publicclass funcs {
public int [][]px;
public int n;
public int T;
public funcs(int a){
int i;
T=1;
for(i=1;i<=a;i++) T*=i;
n=a;
px=new int [T][n];
};
public void exe()
{
int i,j,t;
int k;
int ln=1;
int []tmp;
tmp=new int [2*n];
px[0][0]=0;
//******************** M *************************
for(k=1;k<n;k++)
{
for(i=0;i<=k;i++)
{
tmp[i]=i;
tmp[i+k+1]=i;
}
for(t=1;t<=k;t++)
{
for(i=0;i<ln;i++)
{
for(j=0;j<k;j++) px[ln*t+i][j]=tmp[px[i][j]+t];
px[ln*t+i][k]=t-1;
}
}
for(i=0;i<ln;i++) px[i][k]=k;
ln*=(k+1);
}
//******************** M ***************************
for(i=0;i<T;i++)
{
for(j=0;j<n;j++)
{
System.out.print(px[i][j]);
System.out.print(' ');
}
System.out.print((char)0x0d);
}
}
}
程序中的M段描述的就是这个算法结构。
funcs abc = new funcs(3);
则:
0 1 2
1 0 2
1 2 0
2 1 0
2 0 1
0 2 1
最后若是问题是所有n个编号的球,取出m个排列,允许重复?有上述的两个接口程序,得到这个问题的程序解答很容易,这儿就不列出了。
**************************************************************************************
在做P(n)时,曾想过用第n数插入到所有P(n-1)的排列的各个间隔中,很容易理解,问题是这样的结构需要链表,不是一个好的方式。常常有些有意思的东西,只是抬笔很麻烦,好在昨夜失眠,还是写点什么好了。
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-12-22 14:09
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社