- 逆序对问题 leetCode 剑指51
- 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。
- 输入一个数组,求出这个数组中的逆序对的总数。
- 输入: [7,5,6,4]
- 输出: 5
- 思路: 在归并排序的过程中就能得到逆序对个数 如果在合并数组的过程中 右数组当前的数字小于 左数组当前的数字
- 那么左数组从当前的数字 一直到结束 都与右数组形成逆序对
- 例如 [7,5,6,4]
- 在叶子节点合并后为可得逆序对:[7,5] [6,4]
- 然后[5,7] [4,6]合并的时候4小于5 故5之后所有数字都与4组成逆序对 即[5,4] [7,4]
- 同理可得[7,6]
- 所以全部逆序对个数为[7,5] [6,4] [5,4] [7,4] [7,6] 5个
public class Solution {
public int reversePairs(int[] nums) {
int[] temp = new int[nums.length];
return sort(nums, 0, nums.length-1, temp);
}
private static int sort(int[] arr, int l, int r, int[] temp) {
if (l >= r) {
return 0;
}
int res = 0;
int mid = (l + r) / 2;
res += sort(arr, l, mid, temp);
res += sort(arr, mid+1, r, temp);
if (arr[mid] > arr[mid+1]) {
res += merge(arr, l, mid, r, temp);
}
return res;
}
private static int merge(int[] arr, int l, int mid, int r, int[] temp) {
System.arraycopy(arr, l, temp, l, (r-l)+1);
int i = l, j = mid+1, res = 0;
for (int k = l; k <= r; k++) {
if (i > mid) {
arr[k] = temp[j];
j++;
} else if (j > r) {
arr[k] = temp[i];
i++;
} else if (temp[i] <= temp[j]) {
arr[k] = temp[i];
i++;
} else {
res += mid - i + 1;
arr[k] = temp[j];
j++;
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {7,5,6,4};
System.out.println(new Solution().reversePairs(arr));
}
}