Подсчет инверсий в массиве - PullRequest
95 голосов
/ 03 декабря 2008

Я разрабатываю алгоритм, который выполняет следующие действия: По заданному массиву A[1... n] для каждого i < j найдите все пары инверсий, такие что A[i] > A[j]. Я использую сортировку слиянием и копирую массив A в массив B, а затем сравниваю два массива, но мне трудно понять, как я могу использовать это, чтобы найти число инверсий. Будем весьма благодарны за любые советы или помощь.

Ответы [ 34 ]

0 голосов
/ 22 октября 2017

Реализация подсчета инверсий в массиве с сортировкой слиянием в Swift:

Обратите внимание, что количество свопов увеличивается на

nSwaps += mid + 1 - iL 

(это относительная длина левой части массива минус индекс текущего элемента в левой части)

... потому что это количество элементов, которые элемент в правой части массива должен был пропустить (число инверсий), чтобы отсортировать.

func merge(arr: inout [Int], arr2: inout [Int], low: Int, mid: Int, high: Int) -> Int {
    var nSwaps = 0;

    var i = low;
    var iL = low;
    var iR = mid + 1;

    while iL <= mid && iR <= high {
        if arr2[iL] <= arr2[iR] {
            arr[i] = arr2[iL]
            iL += 1
            i += 1
        } else {
            arr[i] = arr2[iR]
            nSwaps += mid + 1 - iL
            iR += 1
            i += 1
        }
    }

    while iL <= mid {
        arr[i] = arr2[iL]
        iL += 1
        i += 1
    }

    while iR <= high {
        arr[i] = arr2[iR]
        iR += 1
        i += 1
    }

    return nSwaps
}

func mergeSort(arr: inout [Int]) -> Int {
    var arr2 = arr
    let nSwaps = mergeSort(arr: &arr, arr2: &arr2, low: 0, high: arr.count-1)
    return nSwaps
}

func mergeSort(arr: inout [Int], arr2: inout [Int], low: Int, high: Int) -> Int {

    if low >= high {
        return 0
    }

    let mid = low + ((high - low) / 2)

    var nSwaps = 0;
    nSwaps += mergeSort(arr: &arr2, arr2: &arr, low: low, high: mid)
    nSwaps += mergeSort(arr: &arr2, arr2: &arr, low: mid+1, high: high)
    nSwaps += merge(arr: &arr, arr2: &arr2, low: low, mid: mid, high: high)

    return nSwaps
}

var arrayToSort: [Int] = [2, 1, 3, 1, 2]
let nSwaps = mergeSort(arr: &arrayToSort)

print(arrayToSort) // [1, 1, 2, 2, 3]
print(nSwaps) // 4
0 голосов
/ 27 января 2014

Вот мой пример использования Scala:

trait MergeSort {
  def mergeSort(ls: List[Int]): List[Int] = {
    def merge(ls1: List[Int], ls2: List[Int]): List[Int] =
      (ls1, ls2) match {
        case (_, Nil) => ls1
        case (Nil, _) => ls2
        case (lowsHead :: lowsTail, highsHead :: highsTail) =>
          if (lowsHead <= highsHead) lowsHead :: merge(lowsTail, ls2)
          else highsHead :: merge(ls1, highsTail)
      }

    ls match {
      case Nil => Nil
      case head :: Nil => ls
      case _ =>
        val (lows, highs) = ls.splitAt(ls.size / 2)
        merge(mergeSort(lows), mergeSort(highs))
    }
  }
}

object InversionCounterApp extends App with MergeSort {
  @annotation.tailrec
  def calculate(list: List[Int], sortedListZippedWithIndex: List[(Int, Int)], counter: Int = 0): Int =
    list match {
      case Nil => counter
      case head :: tail => calculate(tail, sortedListZippedWithIndex.filterNot(_._1 == 1), counter + sortedListZippedWithIndex.find(_._1 == head).map(_._2).getOrElse(0))
    }

  val list: List[Int] = List(6, 9, 1, 14, 8, 12, 3, 2)
  val sortedListZippedWithIndex: List[(Int, Int)] = mergeSort(list).zipWithIndex
  println("inversion counter = " + calculate(list, sortedListZippedWithIndex))
  // prints: inversion counter = 28 
}
0 голосов
/ 21 декабря 2017

Этот ответ содержит результаты timeit тестов, произведенных кодом в моем основном ответе . Пожалуйста, смотрите этот ответ для деталей!

count_inversions speed test results

Size = 5, hi = 2, 4096 loops
ltree_count_PM2R         : 0.04871, 0.04872, 0.04876
bruteforce_loops_PM2R    : 0.05696, 0.05700, 0.05776
solution_TimBabych       : 0.05760, 0.05822, 0.05943
solutionE_TimBabych      : 0.06642, 0.06704, 0.06760
bruteforce_sum_PM2R      : 0.07523, 0.07545, 0.07563
perm_sum_PM2R            : 0.09873, 0.09875, 0.09935
rank_sum_PM2R            : 0.10449, 0.10463, 0.10468
solution_python          : 0.13034, 0.13061, 0.13221
fenwick_inline_PM2R      : 0.14323, 0.14610, 0.18802
perm_radixR_PM2R         : 0.15146, 0.15203, 0.15235
merge_count_BM           : 0.16179, 0.16267, 0.16467
perm_radixI_PM2R         : 0.16200, 0.16202, 0.16768
perm_fenwick_PM2R        : 0.16887, 0.16920, 0.17075
merge_PM2R               : 0.18262, 0.18271, 0.18418
count_inversions_NiklasB : 0.19183, 0.19279, 0.20388
count_inversion_mkso     : 0.20060, 0.20141, 0.20398
inv_cnt_ZheHu            : 0.20815, 0.20841, 0.20906
fenwick_PM2R             : 0.22109, 0.22137, 0.22379
reversePairs_nomanpouigt : 0.29620, 0.29689, 0.30293
Value: 5

Size = 10, hi = 5, 2048 loops
solution_TimBabych       : 0.05954, 0.05989, 0.05991
solutionE_TimBabych      : 0.05970, 0.05972, 0.05998
perm_sum_PM2R            : 0.07517, 0.07519, 0.07520
ltree_count_PM2R         : 0.07672, 0.07677, 0.07684
bruteforce_loops_PM2R    : 0.07719, 0.07724, 0.07817
rank_sum_PM2R            : 0.08587, 0.08823, 0.08864
bruteforce_sum_PM2R      : 0.09470, 0.09472, 0.09484
solution_python          : 0.13126, 0.13154, 0.13185
perm_radixR_PM2R         : 0.14239, 0.14320, 0.14474
perm_radixI_PM2R         : 0.14632, 0.14669, 0.14679
fenwick_inline_PM2R      : 0.16796, 0.16831, 0.17030
perm_fenwick_PM2R        : 0.18189, 0.18212, 0.18638
merge_count_BM           : 0.19816, 0.19870, 0.19948
count_inversions_NiklasB : 0.21807, 0.22031, 0.22215
merge_PM2R               : 0.22037, 0.22048, 0.26106
fenwick_PM2R             : 0.24290, 0.24314, 0.24744
count_inversion_mkso     : 0.24895, 0.24899, 0.25205
inv_cnt_ZheHu            : 0.26253, 0.26259, 0.26590
reversePairs_nomanpouigt : 0.35711, 0.35762, 0.35973
Value: 20

Size = 20, hi = 10, 1024 loops
solutionE_TimBabych      : 0.05687, 0.05696, 0.05720
solution_TimBabych       : 0.06126, 0.06151, 0.06168
perm_sum_PM2R            : 0.06875, 0.06906, 0.07054
rank_sum_PM2R            : 0.07988, 0.07995, 0.08002
ltree_count_PM2R         : 0.11232, 0.11239, 0.11257
bruteforce_loops_PM2R    : 0.12553, 0.12584, 0.12592
solution_python          : 0.13472, 0.13540, 0.13694
bruteforce_sum_PM2R      : 0.15820, 0.15849, 0.16021
perm_radixI_PM2R         : 0.17101, 0.17148, 0.17229
perm_radixR_PM2R         : 0.17891, 0.18087, 0.18366
perm_fenwick_PM2R        : 0.20554, 0.20708, 0.21412
fenwick_inline_PM2R      : 0.21161, 0.21163, 0.22047
merge_count_BM           : 0.24125, 0.24261, 0.24565
count_inversions_NiklasB : 0.25712, 0.25754, 0.25778
merge_PM2R               : 0.26477, 0.26566, 0.31297
fenwick_PM2R             : 0.28178, 0.28216, 0.29069
count_inversion_mkso     : 0.30286, 0.30290, 0.30652
inv_cnt_ZheHu            : 0.32024, 0.32041, 0.32447
reversePairs_nomanpouigt : 0.45812, 0.45822, 0.46172
Value: 98

Size = 40, hi = 20, 512 loops
solutionE_TimBabych      : 0.05784, 0.05787, 0.05958
solution_TimBabych       : 0.06452, 0.06475, 0.06479
perm_sum_PM2R            : 0.07254, 0.07261, 0.07263
rank_sum_PM2R            : 0.08537, 0.08540, 0.08572
ltree_count_PM2R         : 0.11744, 0.11749, 0.11792
solution_python          : 0.14262, 0.14285, 0.14465
perm_radixI_PM2R         : 0.18774, 0.18776, 0.18922
perm_radixR_PM2R         : 0.19425, 0.19435, 0.19609
bruteforce_loops_PM2R    : 0.21500, 0.21511, 0.21686
perm_fenwick_PM2R        : 0.23338, 0.23375, 0.23674
fenwick_inline_PM2R      : 0.24947, 0.24958, 0.25189
bruteforce_sum_PM2R      : 0.27627, 0.27646, 0.28041
merge_count_BM           : 0.28059, 0.28128, 0.28294
count_inversions_NiklasB : 0.28557, 0.28759, 0.29022
merge_PM2R               : 0.29886, 0.29928, 0.30317
fenwick_PM2R             : 0.30241, 0.30259, 0.35237
count_inversion_mkso     : 0.34252, 0.34356, 0.34441
inv_cnt_ZheHu            : 0.37468, 0.37569, 0.37847
reversePairs_nomanpouigt : 0.50725, 0.50770, 0.50943
Value: 369

Size = 80, hi = 40, 256 loops
solutionE_TimBabych      : 0.06339, 0.06373, 0.06513
solution_TimBabych       : 0.06984, 0.06994, 0.07009
perm_sum_PM2R            : 0.09171, 0.09172, 0.09186
rank_sum_PM2R            : 0.10468, 0.10474, 0.10500
ltree_count_PM2R         : 0.14416, 0.15187, 0.18541
solution_python          : 0.17415, 0.17423, 0.17451
perm_radixI_PM2R         : 0.20676, 0.20681, 0.20936
perm_radixR_PM2R         : 0.21671, 0.21695, 0.21736
perm_fenwick_PM2R        : 0.26197, 0.26252, 0.26264
fenwick_inline_PM2R      : 0.28111, 0.28249, 0.28382
count_inversions_NiklasB : 0.31746, 0.32448, 0.32451
merge_count_BM           : 0.31964, 0.33842, 0.35276
merge_PM2R               : 0.32890, 0.32941, 0.33322
fenwick_PM2R             : 0.34355, 0.34377, 0.34873
count_inversion_mkso     : 0.37689, 0.37698, 0.38079
inv_cnt_ZheHu            : 0.42923, 0.42941, 0.43249
bruteforce_loops_PM2R    : 0.43544, 0.43601, 0.43902
bruteforce_sum_PM2R      : 0.52106, 0.52160, 0.52531
reversePairs_nomanpouigt : 0.57805, 0.58156, 0.58252
Value: 1467

Size = 160, hi = 80, 128 loops
solutionE_TimBabych      : 0.06766, 0.06784, 0.06963
solution_TimBabych       : 0.07433, 0.07489, 0.07516
perm_sum_PM2R            : 0.13143, 0.13175, 0.13179
rank_sum_PM2R            : 0.14428, 0.14440, 0.14922
solution_python          : 0.20072, 0.20076, 0.20084
ltree_count_PM2R         : 0.20314, 0.20583, 0.24776
perm_radixI_PM2R         : 0.23061, 0.23078, 0.23525
perm_radixR_PM2R         : 0.23894, 0.23915, 0.24234
perm_fenwick_PM2R        : 0.30984, 0.31181, 0.31503
fenwick_inline_PM2R      : 0.31933, 0.32680, 0.32722
merge_count_BM           : 0.36003, 0.36387, 0.36409
count_inversions_NiklasB : 0.36796, 0.36814, 0.37106
merge_PM2R               : 0.36847, 0.36848, 0.37127
fenwick_PM2R             : 0.37833, 0.37847, 0.38095
count_inversion_mkso     : 0.42746, 0.42747, 0.43184
inv_cnt_ZheHu            : 0.48969, 0.48974, 0.49293
reversePairs_nomanpouigt : 0.67791, 0.68157, 0.72420
bruteforce_loops_PM2R    : 0.82816, 0.83175, 0.83282
bruteforce_sum_PM2R      : 1.03322, 1.03378, 1.03562
Value: 6194

Size = 320, hi = 160, 64 loops
solutionE_TimBabych      : 0.07467, 0.07470, 0.07483
solution_TimBabych       : 0.08036, 0.08066, 0.08077
perm_sum_PM2R            : 0.21142, 0.21201, 0.25766
solution_python          : 0.22410, 0.22644, 0.22897
rank_sum_PM2R            : 0.22820, 0.22851, 0.22877
ltree_count_PM2R         : 0.24424, 0.24595, 0.24645
perm_radixI_PM2R         : 0.25690, 0.25710, 0.26191
perm_radixR_PM2R         : 0.26501, 0.26504, 0.26729
perm_fenwick_PM2R        : 0.33483, 0.33507, 0.33845
fenwick_inline_PM2R      : 0.34413, 0.34484, 0.35153
merge_count_BM           : 0.39875, 0.39919, 0.40302
fenwick_PM2R             : 0.40434, 0.40439, 0.40845
merge_PM2R               : 0.40814, 0.41531, 0.51417
count_inversions_NiklasB : 0.41681, 0.42009, 0.42128
count_inversion_mkso     : 0.47132, 0.47192, 0.47385
inv_cnt_ZheHu            : 0.54468, 0.54750, 0.54893
reversePairs_nomanpouigt : 0.76164, 0.76389, 0.80357
bruteforce_loops_PM2R    : 1.59125, 1.60430, 1.64131
bruteforce_sum_PM2R      : 2.03734, 2.03834, 2.03975
Value: 24959

Run 2

Size = 640, hi = 320, 8 loops
solutionE_TimBabych      : 0.04135, 0.04374, 0.04575
ltree_count_PM2R         : 0.06738, 0.06758, 0.06874
perm_radixI_PM2R         : 0.06928, 0.06943, 0.07019
fenwick_inline_PM2R      : 0.07850, 0.07856, 0.08059
perm_fenwick_PM2R        : 0.08151, 0.08162, 0.08170
perm_sum_PM2R            : 0.09122, 0.09133, 0.09221
rank_sum_PM2R            : 0.09549, 0.09603, 0.11270
merge_count_BM           : 0.10733, 0.10807, 0.11032
count_inversions_NiklasB : 0.12460, 0.19865, 0.20205
solution_python          : 0.13514, 0.13585, 0.13814

Size = 1280, hi = 640, 8 loops
solutionE_TimBabych      : 0.04714, 0.04742, 0.04752
perm_radixI_PM2R         : 0.15325, 0.15388, 0.15525
solution_python          : 0.15709, 0.15715, 0.16076
fenwick_inline_PM2R      : 0.16048, 0.16160, 0.16403
ltree_count_PM2R         : 0.16213, 0.16238, 0.16428
perm_fenwick_PM2R        : 0.16408, 0.16416, 0.16449
count_inversions_NiklasB : 0.19755, 0.19833, 0.19897
merge_count_BM           : 0.23736, 0.23793, 0.23912
perm_sum_PM2R            : 0.32946, 0.32969, 0.33277
rank_sum_PM2R            : 0.34637, 0.34756, 0.34858

Size = 2560, hi = 1280, 8 loops
solutionE_TimBabych      : 0.10898, 0.11005, 0.11025
perm_radixI_PM2R         : 0.33345, 0.33352, 0.37656
ltree_count_PM2R         : 0.34670, 0.34786, 0.34833
perm_fenwick_PM2R        : 0.34816, 0.34879, 0.35214
fenwick_inline_PM2R      : 0.36196, 0.36455, 0.36741
solution_python          : 0.36498, 0.36637, 0.40887
count_inversions_NiklasB : 0.42274, 0.42745, 0.42995
merge_count_BM           : 0.50799, 0.50898, 0.50917
perm_sum_PM2R            : 1.27773, 1.27897, 1.27951
rank_sum_PM2R            : 1.29728, 1.30389, 1.30448

Size = 5120, hi = 2560, 8 loops
solutionE_TimBabych      : 0.26914, 0.26993, 0.27253
perm_radixI_PM2R         : 0.71416, 0.71634, 0.71753
perm_fenwick_PM2R        : 0.71976, 0.72078, 0.72078
fenwick_inline_PM2R      : 0.72776, 0.72804, 0.73143
ltree_count_PM2R         : 0.81972, 0.82043, 0.82290
solution_python          : 0.83714, 0.83756, 0.83962
count_inversions_NiklasB : 0.87282, 0.87395, 0.92087
merge_count_BM           : 1.09496, 1.09584, 1.10207
rank_sum_PM2R            : 5.02564, 5.06277, 5.06666
perm_sum_PM2R            : 5.09088, 5.12999, 5.13512

Size = 10240, hi = 5120, 8 loops
solutionE_TimBabych      : 0.71556, 0.71718, 0.72201
perm_radixI_PM2R         : 1.54785, 1.55096, 1.55515
perm_fenwick_PM2R        : 1.55103, 1.55353, 1.59298
fenwick_inline_PM2R      : 1.57118, 1.57240, 1.57271
ltree_count_PM2R         : 1.76240, 1.76247, 1.80944
count_inversions_NiklasB : 1.86543, 1.86851, 1.87208
solution_python          : 2.01490, 2.01519, 2.06423
merge_count_BM           : 2.35215, 2.35301, 2.40023
rank_sum_PM2R            : 20.07048, 20.08399, 20.13200
perm_sum_PM2R            : 20.10187, 20.12551, 20.12683

Run 3
Size = 20480, hi = 10240, 4 loops
solutionE_TimBabych      : 1.07636, 1.08243, 1.09569
perm_radixI_PM2R         : 1.59579, 1.60519, 1.61785
perm_fenwick_PM2R        : 1.66885, 1.68549, 1.71109
fenwick_inline_PM2R      : 1.72073, 1.72752, 1.77217
ltree_count_PM2R         : 1.96900, 1.97820, 2.02578
count_inversions_NiklasB : 2.03257, 2.05005, 2.18548
merge_count_BM           : 2.46768, 2.47377, 2.52133
solution_python          : 2.49833, 2.50179, 3.79819

Size = 40960, hi = 20480, 4 loops
solutionE_TimBabych      : 3.51733, 3.52008, 3.56996
perm_radixI_PM2R         : 3.51736, 3.52365, 3.56459
perm_fenwick_PM2R        : 3.76097, 3.80900, 3.87974
fenwick_inline_PM2R      : 3.95099, 3.96300, 3.99748
ltree_count_PM2R         : 4.49866, 4.54652, 5.39716
count_inversions_NiklasB : 4.61851, 4.64303, 4.73026
merge_count_BM           : 5.31945, 5.35378, 5.35951
solution_python          : 6.78756, 6.82911, 6.98217

Size = 81920, hi = 40960, 4 loops
perm_radixI_PM2R         : 7.68723, 7.71986, 7.72135
perm_fenwick_PM2R        : 8.52404, 8.53349, 8.53710
fenwick_inline_PM2R      : 8.97082, 8.97561, 8.98347
ltree_count_PM2R         : 10.01142, 10.01426, 10.03216
count_inversions_NiklasB : 10.60807, 10.62424, 10.70425
merge_count_BM           : 11.42149, 11.42342, 11.47003
solutionE_TimBabych      : 12.83390, 12.83485, 12.89747
solution_python          : 19.66092, 19.67067, 20.72204

Size = 163840, hi = 81920, 4 loops
perm_radixI_PM2R         : 17.14153, 17.16885, 17.22240
perm_fenwick_PM2R        : 19.25944, 19.27844, 20.27568
fenwick_inline_PM2R      : 19.78221, 19.80219, 19.80766
ltree_count_PM2R         : 22.42240, 22.43259, 22.48837
count_inversions_NiklasB : 22.97341, 23.01516, 23.98052
merge_count_BM           : 24.42683, 24.48559, 24.51488
solutionE_TimBabych      : 60.96006, 61.20145, 63.71835
solution_python          : 73.75132, 73.79854, 73.95874

Size = 327680, hi = 163840, 4 loops
perm_radixI_PM2R         : 36.56715, 36.60221, 37.05071
perm_fenwick_PM2R        : 42.21616, 42.21838, 42.26053
fenwick_inline_PM2R      : 43.04987, 43.09075, 43.13287
ltree_count_PM2R         : 49.87400, 50.08509, 50.69292
count_inversions_NiklasB : 50.74591, 50.75012, 50.75551
merge_count_BM           : 52.37284, 52.51491, 53.43003
solutionE_TimBabych      : 373.67198, 377.03341, 377.42360
solution_python          : 411.69178, 411.92691, 412.83856

Size = 655360, hi = 327680, 4 loops
perm_radixI_PM2R         : 78.51927, 78.66327, 79.46325
perm_fenwick_PM2R        : 90.64711, 90.80328, 91.76126
fenwick_inline_PM2R      : 93.32482, 93.39086, 94.28880
count_inversions_NiklasB : 107.74393, 107.80036, 108.71443
ltree_count_PM2R         : 109.11328, 109.23592, 110.18247
merge_count_BM           : 111.05633, 111.07840, 112.05861
solutionE_TimBabych      : 1830.46443, 1836.39960, 1849.53918
solution_python          : 1911.03692, 1912.04484, 1914.69786
0 голосов
/ 03 декабря 2008

Простой ответ O (n ^ 2) состоит в том, чтобы использовать вложенные циклы for и увеличивать счетчик для каждой инверсии

int counter = 0;

for(int i = 0; i < n - 1; i++)
{
    for(int j = i+1; j < n; j++)
    {
        if( A[i] > A[j] )
        {
            counter++;
        }
    }
}

return counter;

Теперь, я полагаю, вы хотите более эффективное решение, я подумаю об этом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...