algorithm - 找到没有相邻元素相同的系列的所有排列?
问题描述
我们得到一个数字列表,其中每个数字要么单独出现,要么重复出现。现在的任务是找到排列的总数,我们可以在其中排列这个数字列表,以便列表上没有两个相邻的元素是相同的。关键是要有效地做到这一点,这就是为什么我正在寻找一种使用动态编程的算法。长度可以非常大,最多 5000 个元素,这就是为什么生成所有案例并检查案例是否正确不是一个好主意的原因。我们只想要总排列的数量,而不是列表的实际排列。
示例案例:[1,1,2,2]
输出:2
[1,2,1,2] 和 [2,1,2,1]
示例案例:[1,2,3,3]
输出:6
[3,1,2,3], [3,2,1,3], [1,3,2,3],[2,3,1,3],[3,1,3,2] 和[3,2,3,1]
示例案例:[1,1,2,2,3,3]
输出:30
解决方案
这个问题可以用包含-排除原则来解决
如果单项s
数为 ,双项对数为d
,则总排列数为
A0 = (s + 2 * d)! / 2^d
现在我们必须减去一对相邻的排列数。有
P1 = (s+2*d-1)! / 2^(d-1)
每个加倍元素的这种排列,以及
A1 = d *(s+2*d-1)! / 2^(d-1)
所有加倍元素的这种排列
现在我们必须添加两对相邻的排列数。有
P2 = (s+2*d-2)! / 2^(d-2)
每对加倍元素的这种排列,以及
A2 = C(d,2) * (s+2*d-2)! / 2^(d-2)
所有可能的加倍元素对的排列(其中C(n,k)
是二项式系数,组合数)。
继续这个过程,改变符号,所以
A(k){k=1..d} = (-1)^k * C(d, k) * (s+2*d-k)! / 2^(d-k)
并对这个序列求和以获得最终结果
对于您的最后一个示例(s=0,d=3
):
6!/2^3 - 3*5!/2^2 + 3*4!/2 - 3! =
720/8 - 360/4 + 72/2 - 6 =
90 - 90 + 36 - 6 = 30
推荐阅读
- listview - 当返回给 ListView 构建器的 List 为空时,如何避免“null”错误?
- python - 如果缺少密钥,如何使用 ceberus 发出警告?
- php - 不推荐使用:不推荐使用带有花括号的数组和字符串偏移访问语法
- amazon-web-services - 如何使用 s3.select_object_content 查询存储桶中的所有对象?
- javascript - × 错误:重新渲染过多。React 限制渲染次数以防止无限循环
- node.js - 未找到模块:错误:无法在 webpack.common.js 中解析
- python - 如果它们都匹配第一列,则比较两个文件,然后替换第 2 列和第 3 列的值(Python)
- dataset - 是否有产品数据集(UPC/EAN 级别)及其回收信息?
- ajax - 使用ajax将值从一个控制器视图传递到另一个控制器视图的codeigniter
- html - 图片在右边,文字在左边