【问题标题】:How to find the number of inversions in an array ? [duplicate]如何找到数组中的反转数? [复制]
【发布时间】:2010-12-29 08:32:53
【问题描述】:

可能重复:
Counting inversions in an array

这是一个phone interview question:“查找数组中的反转数”。我猜他们的意思是 O(Nlog N) 解决方案。我相信它不会比 O(Nlog N) 更好,因为这是排序的复杂性。

similar question的答案可以总结如下:

  1. 计算元素应该移动的一半距离以对数组进行排序:复制数组并对副本进行排序。对于原始数组a[i] 的每个元素,在排序后的副本中找到它的位置j(二分查找),然后将两半的距离相加abs(i - j)/2。

  2. 修改 merge sort :修改 merge 以计算两个排序数组之间的反转并使用修改后的 merge 运行常规 merge sort。

    这有意义吗?还有其他(可能更简单)的解决方案吗?电话面试是不是太难了?

【问题讨论】:

标签: arrays algorithm sorting


【解决方案1】:

其实是分治算法的一种应用,如果你熟悉的话,可以很快想出解决方案。

以 [1 3 8 5 7 2 4 6] 为例,假设我们已经将数组排序为 [1 3 5 8] 和 [2 4 6 7],现在我们需要将这两个数组合并得到总反转次数。

由于我们已经有了每个子数组的反转次数,我们只需要找出数组合并引起的反转次数。每次插入一个元素,比如将2插入[1#3 5 8],就可以知道第一个数组和元素2之间有多少反转(本例中为3对)。然后你可以将它们相加得到合并引起的反转次数。

【讨论】:

  • 让我们知道数组的两半的反转次数。你将如何将它们结合起来得到整个数组的反转次数?
  • @Michael 我已经更新了我的答案
  • 感谢您的更新。据我了解,诀窍是让两个子数组排序。也就是说,我们可以计算每个子数组中的倒数,但为了获得倒数的总数,我们必须对它们进行排序。
  • @ZelluX - 我们如何使用合并排序解决具有重复值的数组作为[1, 3, 4, 5, 6, 4]?
【解决方案2】:

如果数组仅包含小数字(例如,如果它是字符数组),您也可以使用类似计数排序的方法:

inversions = 0
let count = array of size array.Length
for i = 0 to array.Length - 1 do
    for j = array[i] + 1 to maxArrayValue do
        inversions = inversions + count[j]

    count[array[i]] = count[array[i]] + 1

基本上,记录每个元素出现的次数。然后在每一步i,ith 元素生成的反转数等于所有大于i 在i 之前的元素的总和,您可以使用您的计数轻松计算保留。

这将是O(n*eps),其中eps 是数组中元素的域。

在我看来,这绝对更简单。至于效率,只有eps明显小才好。如果是,那么它应该比其他方法更快,因为没有递归。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-11
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-05
    • 1970-01-01
    相关资源
    最近更新 更多