用于计算数组中特定类型的反转的算法

时间:2012-10-02 03:04:06

标签: algorithm

我需要一个算法来计算类型的反转: 如果a具有较低的索引并且a> b,则存在a和b之间的反转。 2b中。

你能想到一个能在O(n logn)中做到的算法吗?

3 个答案:

答案 0 :(得分:2)

可以通过合并排序算法中的小调整来完成。 Counting inversions in an array

在合并阶段的常规标准算法中,您比较左半部分和右半部分的元素,并按左部分中剩余的元素数量增加反转。这里我们不是通过左半部分剩余的元素数量来增加,而是通过左半部分剩余的元素数量增加两倍以上。

答案 1 :(得分:0)

A[1..n]
B[1..n] = copy(A)
sort(B) //n*log(n)

for i = 1 to n-1
  //log(n)
  exists = specialBinarySearch(B, A[i], 1, n)

  //log(n)    
  setHighest(B, A[i], 1, n)
  if exists
    count++

specialBinarySearch(a, key, from, to)
  if from <= to
    mid = from + (to-from)/2

    if a[mid] < floor(key/2)
      return true
    else //must go to left of it to get even smaller value
      specialBinarySearch(a, key, from, mid-1)
  else
    return false

setHighest(a, key, from, to)
  if from <= to
    mid = from + (to-from)/2
    if a[mid] == key
      a[mid] = INT_MAX
    else if a[mid] < key
      setHighest(a, key, mid+1, to)
    else
      setHighest(a, key, from, mid-1)

行。所以,基本上就是这些步骤。

  1. 复制到辅助阵列B.这个O(n)
  2. 使用任何n * log n 算法
  3. 排序
  4. 对于A中的每个元素a,在B中对任何元素B[i]执行二进制搜索,使a > 2*B[i]。为O(log 名词)。 (我编写的算法是为了避免溢出)
  5. 由于我们不必考虑B[i],因此请设置B[i] = infinity使其无法进行比较。另一个二分搜索。为O(log 名词
  6. 重复3和4直到它耗尽。
  7. 所以,我们计算一下

       O(n) + O(n*log(n)) + n*O(log(n))
    => O(n*log(n)) asymptotically
    

答案 2 :(得分:0)

这可以使用动态订单统计数据结构来解决。我知道这种结构有两种选择:

  1. Order statistic tree
  2. Indexable skiplist
  3. 按顺序对数组的每个元素(b),在订单统计数据结构中查找值2b的等级。然后将b插入到订单统计数据结构中。

    2b的等级给出了元素a的数量,它们具有较低的索引且小于2b。这些数字的总和给出了“反转”的数量。