【问题标题】:Distinct permutation subset rank and unrank in DelphiDelphi中不同的置换子集等级和未等级
【发布时间】:2017-11-03 19:38:53
【问题描述】:

问候 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选择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”。

任何帮助将不胜感激。

感谢您的宝贵时间。

【问题讨论】:

  • 等一下,您已经计算了给定空间中的所有 n 排列,其中包含 k 个组。当您已经可以使用公式获得结果时,为什么还需要迭代结果列表?顺便说一句,您正在寻找一个 TDictionary,其中 KEY 是数字 (13),VALUE 是 203。我会使用它!
  • 问候阿尔贝托,我将在非常大的空间中使用它,仅在某些条件下提取几个子集,我无法承受数 TB 的数据库来搜索特定的索引(等级)或子集(未排名)。
  • TDictionary 会有所帮助,就查找速度而言,它是 O(1)。 docwiki.embarcadero.com/CodeExamples/Tokyo/en/…可以帮忙吗?
  • 这不是速度的问题 Alberto,空间,它会产生大量的磁盘/内存空间。

标签: delphi subset distinct permutation rank


【解决方案1】:

这个组合对象有一个特殊的名称,在俄语和法语组合中表示“排列”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 

【讨论】:

  • 问候 MBo,非常感谢您让我走上正轨,当然您的代码可以优化,但仍然可以很好地解释。
猜你喜欢
  • 2011-10-13
  • 1970-01-01
  • 2013-08-27
  • 1970-01-01
  • 1970-01-01
  • 2013-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多