问候Delphian堆垛机。
我搜索了网站,所有“排列等级和排名”相关的讨论,找不到满足我需求的那个。
在德尔福:
有一个数组:
Members: array [0..3] of Byte = (0,1,2,3);
如果想要迭代由3个元素组成的所有不同的排列,可以估计结果列表将由24行组成,按字典顺序排列为:
0 012
1 013
2 021
3 023
4 031
5 032
6 102
7 103
8 120
9 123
10 130
11 132
12 201
13 203
14 210
15 213
16 230
17 231
18 301
19 302
20 310
21 312
22 320
23 321
可以使用“n choose k”公式计算列表的大小,其中“n”表示成员数,“k”表示选择数:
p(n,k) = n! / (n-k)!
p(4,3) = 4! / (4-3)! = (4 x 3 x 2 x 1) / (1 x 1) = 24
我想弄清楚的是如何(不搜索整个列表):
通过提供词典排名,让我们说“13”,可以“取消”并获得子集“203”。
通过提供子集“203”,可以获得词典排名“13”。
非常感谢任何帮助。
感谢您的时间。
答案 0 :(得分:5)
这个组合对象在俄语和法语组合词A(n, k)
中有特殊名称表示“排列”。很容易看出每个数字占据排列列表A(n-1, k-1)
次的第一位。所以我们可以找到给定等级的数字首先出现,反之亦然 - 有第一个数字,我们可以找到等级的间隔。然后继续下一个数字,从列表中删除用过的数字。
function ArrangementByRank(n, k, rank: Integer): string;
function NumArrNK(n, k: Integer): Int64;
var
i: Integer;
begin
Result := 1;
for i := 0 to k - 1 do
Result := Result * (n - i);
end;
var
Dig: array of Byte;
i, j, id, ank: Integer;
begin
Result := '';
SetLength(Dig, n);
for i := 0 to n - 1 do
Dig[i] := i; //initial digit list
for i := 1 to k do begin
ank := NumArrNK(n - i, k - i); //might be optimized
id := rank div ank;
rank := rank mod ank; //prepare for the next round
Result := Result + IntToStr(Dig[id]);
for j := id to n - i - 1 do
Dig[j] := Dig[j + 1]; //squeeze digit list
end;
end;
使用参数5, 3, 15
调用会返回排列1,2,0
。对于反向任务排名可能会被发现为
(Index of 1 in initial list) * A(4,2) + (Index of 2 in squeezed list) * A(3,1) =
1 * A(4,2) + 1 * A(3,1) =
12 + 3 =
15