Search code examples
pythonalgorithmsortingmergesortinversion

Counting the number of inversions in merge sort


I have implemented a merge sort and, as well as sorting, I would like it to compute the number of inversions in the original array.

Below is my attempt at implementing it, which for some reason doesn't compute the number of inversions correctly.

For example, mergeSort([4, 3, 2, 1]) should return (6, [1, 2, 3, 4]).

def mergeSort(alist):
    count = 0  
    if len(alist)>1:
        mid = len(alist)//2
        lefthalf = alist[:mid]
        righthalf = alist[mid:]

        mergeSort(lefthalf)
        mergeSort(righthalf)

        i=0
        j=0
        k=0

        while i < len(lefthalf) and j < len(righthalf):
            if lefthalf[i] < righthalf[j]:
                alist[k]=lefthalf[i]
                i=i+1
            else:
                alist[k]=righthalf[j]
                count +=len(lefthalf[i:])
                j=j+1    
            k=k+1

        while i < len(lefthalf):
            alist[k]=lefthalf[i]
            i=i+1
            k=k+1

        while j < len(righthalf):
            alist[k]=righthalf[j]
            j=j+1
            k=k+1   

   return count, alist

Solution

  • The main problem was not including the counts of sorting left and right sides.

    def mergeSort(alist):
        count = 0
        leftcount = 0
        rightcount = 0
        blist = [] 
        if len(alist) > 1:
           mid = len(alist) // 2
           lefthalf = alist[:mid]
           righthalf = alist[mid:]
           leftcount, lefthalf = mergeSort(lefthalf)
           rightcount, righthalf = mergeSort(righthalf)
    
           i = 0
           j = 0
    
           while i < len(lefthalf) and j < len(righthalf):
             if lefthalf[i] < righthalf[j]:
                 blist.append(lefthalf[i])
                 i += 1
             else:
                 blist.append(righthalf[j])
                 j += 1
                 count += len(lefthalf[i:])
    
           while i < len(lefthalf):
              blist.append(lefthalf[i])
              i += 1
    
           while j < len(righthalf):
              blist.append(righthalf[j])
              j += 1
        else:
            blist = alist[:]
    
        return count + leftcount + rightcount, blist