题目描述

image.png

解题思路

回溯(超时)

  1. int count = 0;
  2. LinkedList<Integer> path = new LinkedList<>();
  3. public void traversal(int[] nums, int startIndex, boolean[] used) {
  4. if (path.size() == 2) {
  5. count++;
  6. return;
  7. }
  8. for (int i = startIndex; i < nums.length; i++) {
  9. if (used[i] == true) continue;
  10. if (!path.isEmpty() && Integer.compare(nums[i], path.getLast()) >= 0) continue;
  11. used[i] = true;
  12. path.add(nums[i]);
  13. traversal(nums, i + 1, used);
  14. path.remove(path.size() - 1);
  15. used[i] = false;
  16. }
  17. }

归并排序中处理

归并排序思路
image.png
此时在合并过程中可以进行比较
例如左边的i为2,右边的j为0,此时i为左边最小的数字,所以左边数字在i之后的数字都是逆序对,此时j++,并把j的数加入排好序的数组。
image.png
此时也增加
image.png
当i的数小于j的数的时候i加入排好序的数组
image.png
算法流程:

  • 终止条件

当有边界小于等于左边界的时候,此时就应该停止递归分割。

  • 递归划分: 计算数组中点 mm ,递归划分左子数组 merge_sort(l, m) 和右子数组 merge_sort(m + 1, r) ;
  • 合并与逆序对统计:

暂存数组 numsnums 闭区间 [l, r] 内的元素至辅助数组 tmp ;
循环合并: 设置双指针 ii , jj 分别指向左 / 右子数组的首元素;
当 i = m + 1时: 代表左子数组已合并完,因此添加右子数组当前元素 tmp[j] ,并执行 j = j + 1 ;
否则,当 j = r + 1 时: 代表右子数组已合并完,因此添加左子数组当前元素 tmp[i] ,并执行 i = i + 1 ;
否则,当 tmp[i]≤tmp[j] 时: 添加左子数组当前元素 tmp[i],并执行 i = i + 1;
否则(即 tmp[i] > tmp[j])时: 添加右子数组当前元素 tmp[j],并执行 j = j + 1 ;此时构成 m - i + 1 个「逆序对」,统计添加至 res ;

  • 返回值: 返回直至目前的逆序对总数 resres

image.png

  1. public int reversePairs(int[] nums) {
  2. if (nums.length == 1) return 0;
  3. this.nums = nums;
  4. tmp = new int[nums.length];
  5. return mergeSort(0, nums.length - 1);
  6. }
  7. int[] nums, tmp;
  8. public int mergeSort(int l, int r) {
  9. if (l >= r) {
  10. return 0;
  11. }
  12. // 递归划分
  13. int mid = (r + l) / 2;
  14. int res = mergeSort(l, mid) + mergeSort(mid + 1, r);
  15. for (int i = l; i <= r; i++) {
  16. tmp[i] = nums[i];
  17. }
  18. // 开始合并
  19. int i = l, j = mid + 1;
  20. for (int k = l; k <= r; k++) {
  21. if (i == mid + 1) {
  22. nums[k] = tmp[j++];
  23. // 注意使用tmp来比较,num会被覆盖
  24. } else if (j == r + 1 || tmp[j] >= tmp[i]) {
  25. nums[k] = tmp[i++];
  26. } else {
  27. nums[k] = tmp[j++];
  28. res += mid - i + 1;
  29. }
  30. }
  31. return res;
  32. }

image.png