归并排序模板 好理解版
class MergeSortTemplate {
public void mergeSort(int[] nums) {
int len = nums.length;
if (len < 2) {
return;
}
int[] temp = new int[len]; // 临时数组,用于合并
divideAndMerge(nums, 0, len - 1, temp);
}
private void divideAndMerge(int[] nums, int left, int right, int[] temp) {
if (left >= right) {
return; // 只有一个元素时直接返回
}
int mid = left + (right - left) / 2;
// 递归处理左半部分
divideAndMerge(nums, left, mid, temp);
// 递归处理右半部分
divideAndMerge(nums, mid + 1, right, temp);
// 如果已经有序,无需合并
if (nums[mid] <= nums[mid + 1]) {
return;
}
// 合并两个有序部分
merge(nums, left, mid, right, temp);
}
private void merge(int[] nums, int left, int mid, int right, int[] temp) {
// 拷贝当前区间到辅助数组
for (int i = left; i <= right; i++) {
temp[i] = nums[i];
}
int i = left; // 左子数组起点
int j = mid + 1; // 右子数组起点
int k = left; // 合并数组起点
// 合并两个有序区间
while (i <= mid && j <= right) {
if (temp[i] <= temp[j]) {
nums[k++] = temp[i++];
} else {
nums[k++] = temp[j++];
}
}
// 左子数组剩余部分
while (i <= mid) {
nums[k++] = temp[i++];
}
// 右子数组剩余部分
while (j <= right) {
nums[k++] = temp[j++];
}
}
public static void main(String[] args) {
int[] nums = {9, 7, 5, 3, 1, 2, 4, 6, 8};
MergeSortTemplate sort = new MergeSortTemplate();
sort.mergeSort(nums);
for (int num : nums) {
System.out.print(num + " ");
}
}
}
这道题
class Solution {
public int reversePairs(int[] nums) {
int len = nums.length;
if (len < 2) {
return 0;
}
int[] temp = new int[len];
return reverse(nums, 0, len - 1, temp);
}
private int reverse(int[] nums, int left, int right, int[] temp) {
if (left == right) {
return 0;
}
int mid = left + (right - left) / 2;
// 左右子数组的逆序对数量
int leftPairs = reverse(nums, left, mid, temp);
int rightPairs = reverse(nums, mid + 1, right, temp);
// 如果两部分已经有序,则无需统计跨区间逆序对
if (nums[mid] <= nums[mid + 1]) {
return leftPairs + rightPairs;
}
// 跨区间逆序对数量
int crossPairs = mergeAndCount(nums, left, mid, right, temp);
return leftPairs + rightPairs + crossPairs;
}
private int mergeAndCount(int[] nums, int left, int mid, int right, int[] temp) {
for (int i = left; i <= right; i++) {
temp[i] = nums[i];
}
int i = left; // 左子数组的起始指针
int j = mid + 1; // 右子数组的起始指针
int count = 0;
int m = left; // 合并的数组索引
while (i <= mid && j <= right) {
if (temp[i] <= temp[j]) {
nums[m++] = temp[i++];
} else {
nums[m++] = temp[j++];
// 统计逆序对数量
count += (mid - i + 1); // 左子数组中,从 i 到 mid 的元素都大于 temp[j]
}
}
// 将左子数组剩余元素拷贝回去
while (i <= mid) {
nums[m++] = temp[i++];
}
// 将右子数组剩余元素拷贝回去
while (j <= right) {
nums[m++] = temp[j++];
}
return count;
}
}