关于数组中N个元素组合成字串问题(200分)

  • 主题发起人 主题发起人 hying95
  • 开始时间 开始时间
H

hying95

Unregistered / Unconfirmed
GUEST, unregistred user!
有数组: cnNum: Array[1..90] of string=('01','02'...'90');
变量 var N: Integer;
问题根据N求出数组中有多少个不同的字符组合.(N不超过10)
举例:N:=4;
01+02+03+04......87+88+89+90 N:=5;
01+02+03+04+05.....
不要光看我举的01+02+03+04 还有其它的05+88+64+33......等所有不同的
03+02+01+04字符位置不同的视为相同.
 
高中数学排列与组合:C<sub>m</sub><sup>n</sup>
 
请贴一段代码
 
用遞歸調用
procedure TForm1.GetAString(Pos, Count: Integer;
Strings: array of string;
Str: string);
var
i: Integer;
begin
for i := Low(Strings) to High(Strings)do
begin
if Pos < Count then
GetAString(Pos + 1, Count, Strings, Str + Strings)
else
Memo1.Lines.Add(Str + Strings);
//輸出組合
end;
end;

GetAString(1, N, cnNum, '')
 
to lasmai
有重复的.为了方便High(cnNum)=5
const
cnNum: Array[0..5] of string=('01','02','03','04','05','06');
运行结果如下:
0101//**这行前后一样的去掉
0102
0103
0104
0105
0106
0201//和0102重复
0202//**这行前后一样的去掉
0203
0204
0205
0206
0301//和0103重复
0302//和0203重复
0303//**这行前后一样的去掉
0304
0305
0306
0401//和0104重复
0402//和0204重复
0403//和0304重复
0404//**这行前后一样的去掉
0405
0406
0501//和0105重复
0502//和0205重复
0503//和0305重复
0504//和0405重复
0505//**这行前后一样的去掉
0506
0601//和0106重复
0602//和0206重复
0603//和0306重复
0604//和0406重复
0605//和0506重复
0606//**这行前后一样的去掉
真正要的是去掉上面注释掉以后的.
 
//是这样吗?
var cArray:Array[0..9] of string =
('01','02','03','04','05','06','07','08','09','10');
procedure TForm1.Button1Click(Sender: TObject);
var i,j,l,n,Value:Integer;
s:Array of String;
Function StrCat(c:Array of string;
size:Integer):String;
var k:Integer;
begin
Result := '';
for k := 0 to sizedo
Result := Result + c[k] + ' ';
end;
begin
n := 5;
SetLength(s,n);
for i := 0 to n - 1do
s := cArray;
Value := 1;
Memo1.Lines.Add(StrCat(s,n-1));
for i := 0 to n - 1do
begin
for l := 0 to n - 1do
s[l] := cArray[l];
for j := n to 9do
begin
s := cArray[j];
Memo1.Lines.Add(StrCat(s,n-1));
inc(Value);
end;
end;
ShowMessage('最多排列组合数是:' + IntToStr(Value));
end;
 
是这样,但不全.
以下是N=3时的结果:
01 02 03
04 02 03
05 02 03
06 02 03
07 02 03
08 02 03
09 02 03
10 02 03
01 04 03
01 05 03
01 06 03
01 07 03
01 08 03
01 09 03
01 10 03
01 02 04
01 02 05
01 02 06
01 02 07
01 02 08
01 02 09
01 02 10
比如:
07 08 09
08 02 05
07 05 06
08 02 06
10 02 06
.....
好象还有很多都没列出来
 
试下这个
procedure TForm1.GetAString(Pos, Count, Index: Integer;
Strings: array of string;
Str: string);
var
i: Integer;
begin
for i := Index to High(Strings)do
begin
if Pos < Count then
GetAString(Pos + 1, Count, i + 1, Strings, Str + Strings)
else
Memo1.Lines.Add(Str + Strings);
//輸出組合
end;
end;

GetAString(1, N, Low(cnNum), cnNum, '')
 
下午试下.
 
to lasmai
好象比下面的这段代码慢了一半,结果相同.能否把它改成函数.输入出TStrings,感觉你上面的要简单一点
function GetStrings(M: integer;var sum: integer;
sArr: Array of integer):TStrings;
var
N: Integer;
i,j :integer;
p : array of integer;//指针数组,其内容为选取的数在s中的标号//长度为m
s : array of integer;//源数组 长度为n
str : string;//输出结果暂存
begin
//初始化p
//此处缺m是否为1的判断,应加入;
N:=High(sArr);
Result:=TStringList.Create;
setlength(p,m);
for i := 0 to m-1do
p:=i;
p[m-1] := p[m-2];
//改;
//初始化s
setlength(s,n);
for i := 0 to n-1do
s:=sArr;//此处的赋值,可根据你的需要
sum:=0;
while truedo
begin
inc(p[m-1]);
str :='';
//得到一个结果
for j:=0 to length(p)-1do
str := str+Add_Space(inttostr(S[p[j]]),'0',2)+' ';
inc(sum);
Result.add(str);
//如果所有指针都排到s之末尾,则找到所有解
//结束循化
if p[0]=(n-m) then
break;
//将指针往后移动
//以遍历所有的数
for i:=1 to m-1do
if p=n-(m-i) then
begin
p[i-1]:= p[i-1]+1;
for j:=i to m-2do
p[j] := p[j-1]+1;
p[m-1]:=p[m-2];
break;
end;
end;
end;
 
公式免费 代码收费。
 
to lasmai
再上来看的时候才发现打错字了,能否把你上面的代码改成函数.效果有了,有点慢,何故?
 
因为用到递归不好改成函数
这样做你看如何?
procedure TForm1.GetAString(Pos, Count, Index: Integer;
Strings: array of string;
Str: string;
AStrList: TStrings);
var
i: Integer;
begin
for i := Index to High(Strings)do
begin
if Pos < Count then
GetAString(Pos + 1, Count, i + 1, Strings, Str + Strings, AStrList)
else
AStrList.Add(Str + Strings);
//结果保存在AStrList
end;
end;

AStringList := TStringList.Create;
GetAString(1, N, Low(cnNum), cnNum, '', AStringList)
同样可以得到结果
 
to lasmai
可以了,谢谢你,费心了,给你加分!!!
 
后退
顶部