假设您有一个整数数组(例如 [1 5 3 4 6])。元素根据以下规则重新排列。每个元素都可以向前(向左)跳跃并在它跳跃的那些索引中滑动元素。该过程从第二个索引(即 5)中的元素开始。它可以选择跳过元素 1,也可以留在自己的位置。如果它确实选择了跳跃,元素 1 会向下滑动到索引 2。假设它确实选择了跳跃,那么我们的结果数组将是 [5 1 3 4 6]。元素 3 现在可以跳过 1 或 2 个位置并重复该过程。如果在一个位置上跳跃 3 次,则数组现在将是 [5 3 1 4 6],如果它在两个位置上跳跃,现在将是 [3 5 1 4 6]。
很容易证明所有可能的元素排列都是可能的。此外,任何最终配置都可以通过一组独特的事件来实现。
问题是,给定一个最终数组和一个源数组,找出从源到达最终数组所需的总跳数。AO(N^2) 的实现很容易找到,但是我相信这可以在 O(N) 或 O(NlogN) 中完成。此外,如果不可能做得比 O(N2) 更好,那么很高兴知道。
例如,如果最终数组是 [3,5,1,4,6],源数组是 [1,5,3,4,6],则答案将为 3。
我的 O(N2) 算法是这样的:你从末尾循环遍历源数组的所有位置,因为我们知道这是最后一个要移动的元素。这里它将是 6,我们检查它在最终数组中的位置。我们计算必要的跳数,并且需要重新排列最终数组以将该元素放在源数组中的原始位置。重新排列步骤遍历数组中的所有元素,并且该过程循环遍历所有元素,因此 O(N^2)。使用 Hashmap 或 map 可以帮助搜索,但是在 O(N^2) 中的每一步之后都需要更新 map。
PS我正在尝试以贝叶斯方式对两个排列之间的相关性进行建模,这是其中的一个子问题。任何关于修改生成过程以使问题更简单的想法也是有帮助的。
编辑:我找到了我的答案。这正是 Kendall Tau 距离所做的。有一个简单的基于合并排序的算法可以在 O(NlogN) 中找到这一点。