等级和等级与约束的组合

时间:2019-06-20 20:14:35

标签: arrays algorithm combinations combinatorics ranking

我想使用元素距离约束对组合进行排名和取消排名。所选元素不能重复。

例如:

n := 10元素可供选择

k := 5个元素被选中

d := 3 2个所选元素之间的最大距离

1,3,5,8,9符合约束条件

1,5,6,7,8与约束不匹配

1,2,3,4,5小于1,2,3,4,6的给定距离约束下,如何对组合进行排名?有没有一种方法可以在不计算具有较小Rank的组合的情况下进行排名?

1 个答案:

答案 0 :(得分:1)

您可以先创建并填充一个二维数组,以记录有效尾部的数量,该数组称为“有效尾数”,将其称为 NVT 。具有给定值的特定位置。例如, NVT [4] [6] = 3,因为在#4位置具有6的组合可以以3种不同的方式结束:(…,6、7),(…,6, 8)和(…,6,9)。

  • 要填充 NVT ,请从 NVT [ n ] […]开始,该行全为1。然后回到原来的位置;例如, NVT [2] [5] == NVT [3] [6] + NVT [3] [7] + NVT [3] [8],因为在位置#3处开始的值为5的“尾巴”将由5加上在位置#4处开始的值为6、7或8的“尾巴”组成。
  • 请注意,我们不在乎是否有有效的方法到达给定的尾巴。例如, NVT [4] [1] = 3是因为有效的尾数(1、2,(1、3、3)和(1、4),即使没有完整的(em)组合形式(...,1 、、 _)。

完成此操作后,就可以计算组合 C 的等级,如下所示:

  • 对于位置1,从位置1开始计数所有有效尾部,且其值小于 C [1]。例如,如果 C 以3开头,则为 NVT [1] [1] + NVT [1] [2],代表以1或2开头的所有组合。
  • 然后对所有后续职位执行相同的操作。这些表示的组合将以与 C 相同的方式开始直到指定位置,但在该位置具有较小的值。
  • 例如,如果 C 为(1、3、5、8、9),则会显示为
    0 +
    NVT [2] [1] + NVT [2] [2])+
    NVT [3] [1] + NVT [3] [2] + NVT [3] [3] + NVT [3] [4]) ( NVT [4] [1] + NVT [4] [2] + NVT [4] [3] + NVT [4] [4] + NVT [4] [5] + NVT [4] [6] + NVT [ 4] [7])+ ( NVT [5] [1] + NVT [5] [2] + NVT [5] [3] + NVT [5] [4] + NVT [5] [5] + NVT [5] [6] + NVT [ 5] [7] + NVT [5] [8])。

相反,您可以找到具有给定等级 r 的组合 C ,如下所示:

  • 为“剩余排名”创建一个临时变量 rr ,最初等于 r
  • 要找到 C [1] —位置#1的值—计算从位置#1开始的有效尾巴,从最小的可能值(即1)开始,一旦超过则停止 rr 。例如,由于 NVT [1] [1] = 66和 NVT [1] [2] = 27,排名75的组合必须以2开头(因为75 ≥66和75 <66 + 27)。然后从 rr 中减去该总和(在这种情况下为75−66 = 9)。
  • 然后对所有后续位置执行相同的操作,请确保记住与先前位置相同的最小值。继续使用 r = 75, C [1] = 2和 rr = 9的示例,我们知道 C [2]≥3;并且由于 NVT [2] [3] = 23 >> rr ,我们立即发现 C [2] = 3。

复杂度分析:

  • 空格:
    • NVT 需要 O nk )空间。
    • 将组合返回为length- k 数组本质上需要 O k )空间;但是如果我们一次返回一个组合值(通过调用回调或打印到控制台等),则计算本身实际上并不依赖于此数组,只需要 O ( 1)多余的空间。
    • 除此之外,其他所有内容都可以在 O (1)空间中进行管理;我们不需要任何递归或临时数组或任何其他东西。
  • 时间:
    • 填充 NVT 需要花费 O nkd )时间。 (注意:如果 d 大于 n ,那么我们可以将 d 设置为等于 n 。)< / li>
    • 给出 NVT ,计算给定组合的排名将花费最坏情况下的 O nk )时间。
    • 给出 NVT ,计算具有给定等级的组合将花费最坏情况下的 O nk )时间。

实施说明:上面的细节有些古怪;如果没有具体的数据需要查看,那么很容易出现一个错误,或者混淆两个变量,或者什么都不会。由于您的示例只有168个有效组合,因此我建议生成所有组合,以便在调试期间可以引用它们。


可能的其他优化:如果您期望 n 很大,并且希望对“组合”和“组合不组合”进行大量查询,那么创建组合可能会很有用第二个数组,我将其称为“ NVTLT ”,以表示“有效尾部的数量少于”,以记录从某个位置开始的有效“尾部”的数量,其值小于< / em>给定值。例如, NVTLT [3] [5] == NVT [3] [1] + NVT [3] [2] + NVT [3] [3] + NVT [3] [4],或者,如果您愿意, NVTLT [3] [5] == NVTLT [3] [4] + NVT [3] [4]。 (您可以将其作为就地转换来完成,完全覆盖 NVT ,因此它是 O nk )传递,没有额外的空间。 )在查询中使用 NVTLT 而不是 NVT 将使您对值进行二进制搜索,而不是线性搜索,从而给出最坏情况的 O k log n )时间而不是 O nk )时间。请注意,此优化甚至比上述优化更为棘手,因此,即使您打算执行此优化,我还是建议从上述内容开始,使其完美运行,然后再添加此优化。