题目
如果一个数组中,任何一个前面的数a,和任意一个后面的数b,如果(a,b)是降序的(a > b),就称为逆序对,返回数组中会有的逆序对。
举例:数组arr{3,1,2,4,0}
从3开始,a = 3 -> 此时的逆序对有(3,1),(3,2),(3.0)
a = 1,2时,有(1,0)(2,0)
a = 4 -> 此时的逆序对有 (4,0)
所以,数组中共有6个逆序对。
分析:
练习一中小和问题中,是按照找右侧比自己大的数的思路,merge时,左右组从头开始比较,如果左组 < 右组,则看右组中有多少数,进行累加。如果相等,则右组数字右移,来解决小和问题。
那么逆序对的思路也大致相同,数组分左右组并进行排序。
- 可以从尾向前遍历,左组 > 右组,则代表 左组当前数 >右组当前数至中点的所有数,所以逆序对共有右组当前位置 减去 中点位置的个数。且左组左移,如果相等或 左组 < 右组,则右组左移。
- 依然从头像尾遍历,如果 左组 > 右组,则代表 左组当前位置至中点的所有数 > 右组当前位置数,所以逆序对共有 中点位置 减去 左组当前位置个。 且右组右移,如果当前相等 或 左组 < 右组,则左组右移。
代码实现:
尾端查找
public static int reverPairNumber(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
return process2(arr, 0, arr.length - 1);
}
public static int process2(int[] arr, int L, int R) {
if (L == R) {
return 0;
}
int M = L + ((R - L) >> 1);
return process2(arr, L, M) +
process2(arr, M + 1, R) +
merge2(arr, L, M, R);
}
public static int merge2(int[] arr, int L, int M, int R) {
int[] help = new int[R - L + 1];
int p1 = M;
int p2 = R;
int ans = 0;
int i = help.length - 1;
while (p1 >= L && p2 >= M + 1) {
ans += arr[p1] > arr[p2] ? p2 - M : 0;
help[i--] = arr[p1] > arr[p2] ? arr[p1--] : arr[p2--];
}
while (p1 >= L) {
help[i--] = arr[p1--];
}
while (p2 >= M + 1) {
help[i--] = arr[p2--];
}
for (int j = 0; j < help.length; j++) {
help[j] = arr[j + L];
}
return ans;
}
头部查找
public static int reversePairs(int[] nums) {
if (nums == null || nums.length < 2) {
return 0;
}
return process(nums, 0, nums.length - 1);
}
public static int process(int[] nums, int L, int R) {
if (L == R) {
return 0;
}
int mid = L + ((R - L) >> 1);
return process(nums, L, mid) + process(nums, mid + 1, R) + merge(nums, L, mid, R);
}
public static int merge(int[] nums, int L, int M, int R) {
int[] help = new int[R - L + 1];
int p1 = L;
int p2 = M + 1;
int ans = 0;
int index = 0;
while (p1 <= M && p2 <= R) {
ans += nums[p1] > nums[p2] ? M - p1 +1 : 0;
help[index++] = nums[p1] <= nums[p2] ? nums[p1++] : nums[p2++];
}
while (p1 <=M) {
help[index++] = nums[p1++];
}
while (p2 <= R) {
help[index++] = nums[p2++];
}
for (int j = 0; j < help.length; j++) {
nums[L + j] = help[j];
}
return ans;
}