题目
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
思路
- 初见思路
顺序扫描数组,和后面的每个数字进行比较,如果大于后面的数字count++
评估:很明显一个O(n^2)的算法,不能符合对时间复杂度的要求。 - 改进思路(书本解法)
分析:逆序对的特点是“前面 > 后面”,所以将数组进行划分直至单元素,合并统计“前面 > 后面”的数量,直至归并排序完毕。
总体思路:
左内部有序,统计个数 >>>> 右内部有序,统计个数 >>>> “合并”,统计前区域中元素大于后区域中元素的数量 >>>> left + right + count;
MyCode
public class InversePairs {
public int inversePairs(int[] array) {
if (array == null || array.length == 0)
return 0;
return countInversePairs(array, 0, array.length - 1);
}
public int countInversePairs(int[] array, int start, int end) {
/**等价于归并排序中的左右排序,然后合并*/
if(start < end){
int mid = (start + end) / 2;
int left = countInversePairs(array, start, mid);
int right = countInversePairs(array, mid+1, end);
int[] tempArray = new int[end - start + 1];
int index = tempArray.length-1, index1 = mid, index2 = end;
int count = 0;
while(index1 >= start && index2 >= mid+1){
if(array[index1] > array[index2]){
count += (index2 - mid);
tempArray[index--] = array[index1--];
}else{
tempArray[index--] = array[index2--];
}
}
while(index1 >= start){
tempArray[index--] = array[index1--];
}
while(index2 >= mid+1){
tempArray[index--] = array[index2--];
}
//将有序的数组复制回原数组中,保证可以正常递归
for(int i = 0; i<tempArray.length; i++){
array[start++] = tempArray[i];
}
return left + right +count;
}
return 0;
}
public static void main(String[] args){
InversePairs pairs = new InversePairs();
int[] array = {7,5,4,6};
//pairs.inversePairs(array);
System.out.println(pairs.inversePairs(array));
for(int iter : array)
System.out.print(iter + " ");
}
}