题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。
输入描述:
题目保证输入的数组中没有的相同的数字
示例:
在数组{7,5,6,4}中,一共存在五个逆序对,分别是(7,6)、(7,5)、(7,4)、(6,4)、(5,4)
练习地址
lc
实现
方法:归并排序复杂度O(nlogn)
归并排序需要长度为n的辅助数组,相当于使用空间O(n)换时间效率提升。
public static int inversePairsCore(int[] arr, int[] copy, int start, int end) {
if (start == end) {
copy[start] = arr[start];
return 0;
}
int len = (end - start) / 2;
// 分解
int left = inversePairsCore(copy, arr, start, start + len);
int right = inversePairsCore(copy, arr, start + len + 1, end);
// i初始化为前半段最后一个数字的下标
int i = start + len;
//j初始化为后半段最后一个数字的下标
int j = end;
int indexCopy = end;
int count = 0;
while (i >= start && j >= start + len + 1) {
//p1指针i指向的数字>p2指针j指向的数字,表明有逆序对
if (arr[i] > arr[j]) {
// 将较大数a[i]复制到辅助数组copy,确保递增
copy[indexCopy--] = arr[i--];
//包括a[j]和之前的数都小于a[i],加上个数
count += j - start - len;
} else {
//不存在逆序,较大拷贝到copy
copy[indexCopy--] = arr[j--];
}
}
for (; i >= start; --i) {
copy[indexCopy--] = arr[i];
}
for (; j >= start + len + 1; j--) {
copy[indexCopy--] = arr[j];
}
return left + right + count;
}
}
Test
public static void main(String[] args) {
int[] arr = {7, 5, 6, 4};// 5
System.out.println(inversePairs(arr));
int[] arr2 = {1, 2, 3, 4, 5, 6, 7, 0}; // 7
System.out.println(inversePairs(arr2));
}