题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。
输入一个数组,并求出这个数组中的逆序对的总数P,并将P对1000000007取模输出、
输入描述:保证数组中没有相同的数字,size <= 2*10^5
输入:1,2,3,4,5,6,7,0 输出:7
思路: 1. 显然全部遍历一遍是可以求出来,时间复杂度为O(n^2)
2. 实际上就是个归并排序,加了个变量count来计算,拆完合并时,因为归并的是两个有序的,那么前半部分某个大于后半部分某个,那么前半部分的某个后面的所有和后半部分都构成逆序对。就加一句count = mid - i + 1;
注意:这里由于题目明确说了结果取模,就是考虑到结果是int的话可能会出现越界情况,所以一帮自己做题目要注意可以使用long类型~
public class Solution { public int InversePairs(int [] array) { return revered(array); } public static int revered(int[] arr){ return mergeSort(arr, 0, arr.length-1)%1000000007; } private static int mergeSort(int[] arr, int l, int r) { int cnt = 0; if(l < r){ int mid = (l+r)/2; cnt += mergeSort(arr, l, mid); //左边逆序数量 if(cnt>=1000000007)//数值过大求余 { cnt%=1000000007; } cnt += mergeSort(arr, mid+1, r); //右边逆序数量 if(cnt>=1000000007)//数值过大求余 { cnt%=1000000007; } cnt += merge(arr, l, mid, r); //合并两部分,并计算数量 if(cnt>=1000000007)//数值过大求余 { cnt%=1000000007; } } return cnt; } private static int merge(int[] arr, int l, int mid, int r) { int[] aux = new int[r - l + 1]; for(int i=l; i <= r; i++){ aux[i-l] = arr[i]; } int i = l, j = mid + 1; int cnt = 0; for(int k = l; k <= r; k ++){ //判断索引的合法性 if(i > mid){ arr[k] = aux[j-l]; j ++; }else if(j > r){ arr[k] = aux[i - l]; i ++; }else if(aux[i - l] < aux[j - l]){ arr[k] = aux[i - l]; i ++; }else{ cnt += mid - i + 1; if(cnt>=1000000007)//数值过大求余 { cnt%=1000000007; } arr[k] = aux[j - l]; j ++; } } return cnt; } //暴力 public static int rever(int[] arr){ int len = arr.length; int count = 0; for(int i = 0; i < len; i ++){ for(int j = i; j < len; j++){ if(arr[i] > arr[j]){ count++; } } } return count; } }对归并排序的本质理解清楚~~