我需要一种算法,可以将排列中的运行映射到单个数字,但也可以减少后续数字。
因此,运行是排列中有序且有序的一组连续数字。在列表中,1;2;3;5;6;4 有两个运行,1;2;3 和 5;6。我想用一个数字替换这些,最少,所以如果在删除运行后,我们有 4 个元素的排列,排列使用数字 1 ... 4。在上面,我们必须减少两次运行. 第一次运行将是 1,4 转换为 2,[5;6] 转换为 3,以保持第二个标准。如果我对减少的排列进行排序,然后从映射中扩展内部元素,并对原始排列进行排序,我将得到相同的结果。结果的排列不应该有任何运行。
例如(我已经突出显示了运行):
(1;2;3;4;5;6) => 1 //Mappings: 1->1;2;3;4;5;6
(2;3;4);1;(5;6) => 2 1 3 // Mappings: 2->2;3;4, and 3->5;6
(3;4);(1;2);(5;6) => 2 1 3 // Mappings: 2->3;4, and 1->1;2 and 3->5;6
现在,我正在传递列表并制作列表列表,对运行进行分组。实际上,第二部分是制作干净解决方案的困难部分。我想到了天真的方法,很好奇是否有人有一些聪明的技巧可以做得比我的更好,我就像 O(2n + n log n),
- 用运行的头元素替换运行并将该数据插入哈希表(用于可恢复性)
- 排序以使用其排序索引创建缺失数字的映射。[1;6;5;4] 将输出 [(1,1);(4,2);(5,3);(6,4)]
- 将步骤 1 中的列表替换为步骤 2 中创建的地图并更新哈希表以进行翻译。
再次运行一个例子:
步骤 1:用运行的头元素替换运行并将数据插入哈希表 [1;3;4;2;5;6;] -> [1;3;2;5] 第 2 步:排序数组以创建地图 [1235],所以我们知道,在前面的数组中,1 映射到 1、2 到 2、3 到 3、4 到 5。 第 3 步:从第 1 步开始对数组进行上述翻译。 [1;3;2;4]
如果我对这个排列进行排序并重构:[1;2;3;4], 3->3;4 和 4->5;6 我得到 1;2;3;4;5;6。也排序了。
我正在使用列表,因此首选功能方法。无需代码。当然,欢迎所有想法。
编辑:
默维尔登:
我不清楚映射的精确条件是什么。为什么不允许只为具有 N 次运行的排列生成排列 [1,2,...,N]?您似乎更喜欢将运行映射到该运行的数字,但是(因为这并不总是可能的)您似乎允许一些自由。–
我不喜欢将一个运行映射到该运行中的一个数字(见上图!),但我需要保留一个ordering。排列 [1;2;3...N]是一次运行,因此可以进一步减少。这就是它无效的原因。该顺序将在另一个算法的进一步操作中很重要,但可以在最后扩展各个元素以挽救原始排列。