数组中的逆序对

本贴最后更新于 2621 天前,其中的信息可能已经沧海桑田

题目描述

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数 P。并将 P 对 1000000007 取模的结果输出。 即输出 P%1000000007

输入描述:
题目保证输入的数组中没有的相同的数字数据范围: 对于%50的数据,size<=10^4 对于%75的数据,size<=10^5 对于%100的数据,size<=2*10^5

示例 1

输入
1,2,3,4,5,6,7,0
输出
7

解题思路

  • 把长度为 4 的数组分解成两个长度为 2 的子数组;

  • 把长度为 2 的数组分解成两个长度为 1 的子数组;

  • 把长度为 1 的子数组 合并、排序并统计逆序对

  • 把长度为 2 的子数组合并、排序,并统计逆序对。

计算逆序对示意图

如图所示,在计算完成子数组的逆序对合并之后,需要按照大小进行排序,以免在以后的统计过程中再重复统计。

子数组统计逆序对过程与合并过程如下图所示。

子数组逆序对统计过程与合并过程

首先用两个指针指向数组末尾,比较两数字,如果第一个数组数字大,则构成逆序对,且数目等于第二个数组指针左边的数目(包括指针数字),否则不构成逆序对。较大值的指针在统计完逆序对后向左移动,并把较大值复制到新数组中的最右无值处。

代码

函数中 array 和 copy 互换是因为辅助数组只起到存储数组的作用,存储完后的数组在下一个迭代中才起作用,所以直接调换顺序更方便。

public class Solution { public int InversePairs(int [] array) { int length = array.length; if (length <= 0) return 0; int[] copy = new int[length]; for (int i = 0; i < length; i++) { copy[i] = array[i]; } long count = InversePairsCore(array, copy, 0, length-1); return count % 1000000007; } private long InversePairsCore(int[] array, int[] copy, int start, int end) { if (start == end) { copy[start] = data[start]; return 0; } int length = (end-start)/2; long left = InversePairsCore(copy, array, start, start+length); long right = InversePairsCore(copy, array, start+length+1, end); int i = start+length; int j = end; int indexcopy = end; long count = 0; while (i >= start && j >= start+length+1) { if (array[i] > array[j]) { copy[indexcopy--] = array[i--]; count = count + j - start - length; } else { copy[indexcopy--] = array[j--]; } } for (; i >= start; i--) { copy[indexcopy--] = array[i]; } for (; j >= start+length+1; j--) { copy[indexcopy--] = array[j]; } return left+right+count; } }

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...