归并排序求逆序对

归并排序

归并排序是我们最常使用的排序算法之一,作用是将两个或两个以上的有序数组合并成为一个新的数组,主要使用的是分治和递归的思想;

步骤

将数组分为等长的两部分,然后合并成一个新的数组,照这个思想对两半部分分别进行递归,即可;

代码
/**
 * @Author: Taoyongpan
 * @Date: Created in 10:11 2018/3/27
 */
public class InversePairsMain {
    private static int count = 0;
    public static void main(String[] args){
        int[] arr = {1,2,3,4,5,6,7,0};
//        System.out.println(InversePairs(arr));
        InversePairs(arr);
        for (int i = 0 ; i< arr.length;i++)
            System.out.println(arr[i]);
    }

    public static void InversePairs(int [] arr) {
        if (arr==null||arr.length<1){
            return;
        }
        mergeSort(arr,0,arr.length-1);
//        return count%1000000007;
    }
    public static void mergeSort(int[] arr,int left,int right){
        if (left >= right){
            return;
        }
        int mid = left+((right-left)>>1);
        mergeSort(arr,left,mid);
        mergeSort(arr,mid+1,right);
        merge(arr,left,right,mid);
    }
    public static void merge(int[] arr,int left,int right,int mid){
        int[] temp = new int[right-left+1];
        int i = left;
        int j = mid+1;
        int n = 0;
        while (i<=mid&&j<=right){
            if (arr[i]<=arr[j]){
                temp[n++] = arr[i++];
            }else {
//                count+=mid+1-i;
                temp[n++] = arr[j++];
            }
        }
        while (i<=mid){
            temp[n++] = arr[i++];
        }
        while (j<=right){
//            count+=mid+1-i;
            temp[n++] = arr[j++];
//            if (count>=1000000007)
//                count%=1000000007;
        }
        for (int t = 0 ; t < temp.length;t++){
            arr[left+t] = temp[t];
        }
    }
}

归并排序的用途

使用归并排序可以求逆数对问题;直接上代码,根据代码讲解问题:

/**
 * @Author: Taoyongpan
 * @Date: Created in 10:11 2018/3/27
 */
public class InversePairsMain {
    private static int count = 0;
    public static void main(String[] args){
        int[] arr = {1,2,3,4,5,6,7,0};
        System.out.println(InversePairs(arr));
    }

    public static int InversePairs(int [] arr) {
        if (arr==null||arr.length<1){
            return 0;
        }
        mergeSort(arr,0,arr.length-1);
        return count;
    }
    public static void mergeSort(int[] arr,int left,int right){
        if (left >= right){
            return;
        }
        int mid = left+((right-left)>>1);
        mergeSort(arr,left,mid);
        mergeSort(arr,mid+1,right);
        merge(arr,left,right,mid);
    }
    public static void merge(int[] arr,int left,int right,int mid){
        int[] temp = new int[right-left+1];
        int i = left;
        int j = mid+1;
        int n = 0;
        while (i<=mid&&j<=right){
            if (arr[i]<=arr[j]){
                temp[n++] = arr[i++];
            }else {
                count+=mid+1-i;
                temp[n++] = arr[j++];
            }
        }
        while (i<=mid){
            temp[n++] = arr[i++];
        }
        while (j<=right){
            count+=mid+1-i;
            temp[n++] = arr[j++];
        }
        for (int t = 0 ; t < temp.length;t++){
            arr[left+t] = temp[t];
        }
    }
}

我们求逆数对个数的时候,知识在两个有序数组合并的过程中,当arr[i]>arr[j]的时候会产生逆数对,此时说明,这个有序数组从i位置开始后面的数都大于arr[j],此时产生mid-i+1个逆数对,当数组合并完成的时候,就能统计出整个数组包含的逆数对个数;

    原文作者:Taoyongpan
    原文地址: https://www.jianshu.com/p/928d29ebe3c5
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞