我正在搜索一种算法,该算法可为我提供具有特定强度的下一个排列。 长度为n的排列由元素(1,2,3,... n)定义
排列的强度是什么?
长度为10的置换的强度定义为|a1-a2|+|a2-a3|+...+|a9-a10|+|a10-a1|
。
例如:
(1,2,3,4,5,6)
具有实力10
(1,2,6,3,4,5)
具有实力14
是否存在一个公式来计算给定强度和长度的下一个排列,还是需要计算所有元素?
是否可以对子集进行排名/取消排名?
下一个置换函数应在由给定强度和长度定义的子集中返回下一个字典顺序,而不计算中间置换的不同强度。
答案 0 :(得分:0)
这是组合学中一个很好掩盖的问题。首先,请注意,这是一个整数环。线性“数组”是一种实现选择,而不是强度分析的一部分。让我们来看第二种情况,表示为(1,2,6,3,4,5)
:
1
5 2
4 6
3
每个元素都以正好两个词出现。因此,我们对元素进行了简单的线性组合,系数为-2,02。如果元素大于两个邻居(例如5
),则系数为2
;如果小于两个邻居(例如1
),则为-2;如果介于两者之间,则两个abs
操作将取消,并且为0(例如4
)。
引理:强度必须为偶数。
因此,求和和某些变换可以通过简单的分析就足够容易地进行检查。最大的数字始终具有+2的系数;最小的系数始终为-2。
您可以通过找到可互换的元素来找到“近亲”排列。例如,您可以始终互换最大的两个元素(6和5)和/或最小的两个元素(1和2),而不会影响强度。例如,6和5可以互换,因为它们严格大于邻居:
(6-2) + (6-3) + (5-1) + (5-4) =
(5-2) + (5-3) + (6-1) + (6-4) =
2*6 + 2*5 - 2 - 3 - 1 - 4
1和2可以互换,即使它们是相邻的,也有类似的原因……除了只有三个术语,其中一个涉及到这对:
(5-1) + (2-1) + (6-2) =
(5-2) + (2-1) + (6-1) =
5 + 6 - 2*1
取决于数字集的分布,可能会有更直接的方法来构造具有给定强度的环。由于尚未在排列中定义顺序,因此我们无法确定“下一个”。但是,简单的一点是要注意,给定排列的旋转和反射将具有相同的强度:
(1,2,6,3,4,5)
(2,6,3,4,5,1)
(6,3,4,5,1,2)
...
(5,4,3,6,2,1)
(4,3,6,2,1,5)
...
这会让你动起来吗?
添加了w.r.t. OP更新:
有几种简单的强度不变交换。我已经提到了两个极端对(6-5)和(1-2)。您还可以交换相邻的连续数字:在上面的示例中,该数字会加上(4-5)和(3-4)。从简单的代数性质,您通常可以识别2元素交换或3元素旋转(尊重词典序位置的增加),该旋转会生成下一个所需的排列。例如:
(5, 6, 1, 3, 4, 2)
(5, 6, 1, 4, 2, 3) rotate 3, 4, 2
(5, 6, 1, 4, 3, 2) swap 2, 3
但是,以这种方式很难找到顺序的中断。例如,大胆地更改第一个或第二个元素并不是那么干净:
(5, 6, 3, 1, 4, 2)
(5, 6, 3, 2, 4, 1) swap 1, 2 -- easy
(6, 1, 2, 4, 5, 3) wholesale rearrangement --
hard to see that this is the next strength=14
我觉得找到这些将需要一套代数规则,这些规则将找到简单的举动并消除无效的举动(例如,在上面的“批发重排”之前生成563421)。但是,遵循这些规则通常要比处理所有排列花费更多的时间。
我很想知道我在这最后一点上是错的。 :-)