题目:
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序数对。一个排列中逆序的总数就称为这个排列的逆序数。如{2,4,3,1}中,2和1,4和3,4和1,3和1是逆序数对,因此整个数组的逆序数对个数为4,现在给定一数组,要求统计出该数组的逆序数对个数。
解法一:冒泡法
类似于冒泡排序,假设数组长度为n,设置一个计数count,从i=0到i=n-1进行遍历,如果符合逆序数对条件,则将count加1。代码如下:
public static void main(String[] args) {
int[] array = {2,4,3,1};
int count = method(array);
System.out.println("逆序数对个数为:" + count);
}
private static int method(int[] array) {
int count = 0;
for(int i=0; i array[j]) {
count++;
}
}
}
return count;
}
逆序数对个数为:4
不难看出,该算法的时间复杂度为0(n^2)。
解法二:归并法
举例说明,有如下两个数组,{1,3,5}和{2,4},采用归并排序步骤如下:
(1)取出第一个数组中的1.
(2)取出第二个数组中的2,此时2与第一个数组中的3和5可以构成逆序数对。
(3)取出第一个数组中的3.
(4)取出第二个数组中的4,此时4与第一个数组中的5可以构成逆序数对。
从上面的分析不难看出,可以用类似于归并排序算法来计算逆序数对的个数。归并排序的时间复杂度为O(nlogn),因此该方法求取逆序数对个数的时间复杂度也为O(nlogn)。
代码如下:
定义计数的成员变量:
private static int count = 0;
private static void mergeMethod(int[] array) {
int[] temp = new int[array.length];
mergeSort(array, 0, array.length - 1, temp);
}
private static void mergeSort(int[] array, int first, int last, int[] temp) {
if(first < last) {
int mid = (last + first) / 2;
mergeSort(array, first, mid, temp);
mergeSort(array, mid + 1, last, temp);
mergeArray(array, first, mid, last, temp);
}
}
private static void mergeArray(int[] array, int first, int mid, int last,
int[] temp) {
int i = first, m = mid;
int j = mid + 1, n = last;
int k = 0;
while(i <= m && j <= n) {
if(array[i] < array[j]) {
temp[k++] = array[i++];
}
else {
temp[k++] = array[j++];
count += m - i + 1;
}
}
while(i <= m) {
temp[k++] = array[i++];
}
while(j <= n) {
temp[k++] = array[j++];
}
for(i=0; i
逆序数对个数为:4