面试题51:数组中的逆序对

/*

 * 面试题51:数组中的逆序对

 * 题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。

 * 输入一个数组,求出这个数组中的逆序对的总数P。并将P1000000007取模的结果输出。 即输出P%1000000007

 * 思路:过程:先把数组分割成子数组,先统计出子数组内部的逆序对的数目,然后再统计出两个相邻子数组之间的逆序对的数目。

 * 在统计逆序对的过程中,还需要对数组进行排序。如果对排序算法很熟悉,我们不难发现这个过程实际上就是归并排序。

 * 归并排序的改进,把数据分成前后两个数组(递归到分成很多个数组,每个数组仅有一个数据项),再合并数组,

 * 合并时,出现前面的数组值array[start]大于后面数组值array[end]时;

 * 则前面数组array[start]~array[mid]都是大于array[end]的,count += mid+1 - start

 */

 

 

public class No51InversePairs {

 

    public static void main(String[] args) {

       No51InversePairs n = new No51InversePairs();

       int[] arr = {7, 5, 6, 4};

       System.out.println(n.InversePairs(arr));

    }

 

    int count = 0;

    public int InversePairs(int[] array) {

       if (array == null || array.length == 0) {

           return 0;

       }

      

       mergeSort(array, 0 ,array.length - 1);

       return count;

    }

    private void mergeSort(int[] data, int start, int end) {

       int mid = (start + end) / 2;

       if (start < end) {

           mergeSort(data, start, mid);

           mergeSort(data,mid + 1, end);

           merge(data, start, mid, end);

       }

    }

    private void merge(int[] data, int start, int mid, int end) {

       int arr[] = new int[end - start + 1];

       int c = 0;

       int s = start;

       int index = mid + 1;

      

       while (start <= mid && index <= end) {

           if (data[start] < data[index]) {

              arr[c++] = data[start++];

           } else {

              arr[c++] = data[index++];

              count += mid - start + 1;

              count %= 1000000007;

           }

          

       }

      

       while (start <= mid) {

           arr[c++] = data[start++];

       }

      

       while (index <= end) {

           arr[c++] = data[index++];

       }

      

       for (int d : arr) {

           data[s++] = d;

       }

      

    }

 

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值