3

I am looking for an algorithm to solve this problem:

Given 2 arrays, A and B which are both permutations of [1..n], what is the number of inversions between these 2?

An inversion here would be when a pair elements (i,j) this holds:

if A.indexOf(i) > A.indexOf(j) && B.indexOf(i) < B.indexOf(j)

or

if A.indexOf(i) < A.indexOf(j) && B.indexOf(i) > B.indexOf(j)

I know that there exist multiple ways to do this when you can assume the first array is sorted, like counting the inversions while doing MergeSort, but I have 2 non-sorted arrays.

Example:

A = [6,3,4,1,2,5] and B = [3,5,2,6,1,4]
No. of inversions = 9
6 has a lower index than 3 in A, but a higher index than 3 in B. This is an inversion.

I am hoping to achieve this in O(n log n) time complexity using a Divide and Conquer approach.

van Leemhuyzen
  • 133
  • 1
  • 10
  • Why did you remove your other question about Implementing Breath First Search with OpenCL? – VMAtm Jan 30 '17 at 18:08
  • I contacted my teacher and I already got the solution thanks to him, so I felt the question was no longer needed here. – van Leemhuyzen Jan 30 '17 at 19:40
  • It's better to introduce your own answer for a future visitors rather than delete a good question. – VMAtm Feb 09 '17 at 20:08

2 Answers2

4

In order to do this, we can make a simple substitution (taken from your example): 6->1, 3->2, 4->3, 1->4, 2->5, 5->6. Thus, the first list becomes [1,2,3,4,5,6] and the second becomes [2,6,5,1,4,3]. Then, we can run a simple O(n log n) algorithm for computing the number of inversions in the second list, which gives the answer.

This transformation can be done in O(n) operations using the additional list of indexes. ind[i] will be the index of a given number in the first list,so, if A[1]=6, then ind[6]=1.

Code for constructing the ind array:

    var A = new List<int> {6, 3, 4, 1, 2, 5};
    foreach (var num in A) Console.Write(num + " ");
    Console.WriteLine("");

    var indexes = new int[7];
    for (var i = 0; i < 6; ++i)
        indexes[A[i]] = i + 1;

    for (var i = 1; i < 7; ++i) Console.Write(indexes[i] + " ");
    Console.WriteLine("");

Then, given this array (in the case of this example [4,5,2,3,6,1]) we can make the substitution using resultArray[i] = ind[B[i]];

Code for constructing the substituted array:

    var B = new List<int> {3, 5, 2, 6, 1, 4};

    var resultList = new List<int>();
    for (var i = 0; i < 6; ++i)
        resultList.Add(indexes[B[i]]);

    for(var i = 0; i < 6; ++i)
        Console.Write(resultList[i] + " ");

Then we can just run the algorithm for computing the permutations in the last array, which will be the answer. (I can give the code for computing permutations in O(n log n), but i think that was not the problem here).

h8red
  • 713
  • 4
  • 17
  • Why does above method mentioned in answer differ in the number of inversions than the kendall tau method mentioned in the question? `Consider this example where A = 1, 4, 2, 3, 0 and B = 3, 4, 0, 2, 1. I get inversion as 7 if I follow steps mentioned in the answer whereas I get inversions as 3 with kendall tau method` – harshk17 Sep 18 '17 at 15:27
  • @h8red Can you please answer the question asked in above comment – harshk17 Sep 24 '17 at 04:44
0

Won't this work for you ( O(N^2) time complexity though ):

        int[] A = ...;
        int[] B = ..;

        int count = 0;

        for (int i = 0; i < A.Length-1; i++) {
            for (int j = i+1; j < A.Length; j++) {
                if ((A[i] > A[j] && B[i] < B[j]) || (A[i] < A[j] && B[i] > B[j])) {
                    count++;
                }
            }
        }
Tamas Ionut
  • 4,240
  • 5
  • 36
  • 59
  • Thanks for your comment, but I'm afraid O(n^2) is not fast enough. I'm aiming for O(n log n) using Divide and Conquer. – van Leemhuyzen Mar 11 '16 at 14:26
  • There is also an explanation here in O(n Log n) => http://www.geeksforgeeks.org/counting-inversions/ ; Try fiddling in the B as a comparation metric instead of indexes – Tamas Ionut Mar 11 '16 at 14:38
  • What exactly do you mean by that? Do I have to try and manipulate the arrays so that 1 is a sorted array 1..n? – van Leemhuyzen Mar 11 '16 at 15:33
  • You just need to compare, not against indexes (A[i],A[j]) and (i,j), but against different target: (A[i],A[j]) and (B[i],B[j]) – Tamas Ionut Mar 11 '16 at 15:36