题目

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

示例 1:

输入: [7,5,6,4]
输出: 5

限制:

0 <= 数组长度 <= 50000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

1.分治法(归并排序思想)
当left数组的数字比较小时,能确定右边产生多少逆序对

  1. /**
  2. * @param {number[]} nums
  3. * @return {number}
  4. */
  5. var reversePairs = function (nums) {
  6. // 分治思想
  7. // 类似给并排序
  8. // a: [5, 7] b: [4, 6] 进行按顺序归并 l, r分别指向a, b
  9. // l r
  10. // 1.[4] < [5],r 右移一位
  11. // 2.[5] < [6], l 右移一位,发现:b[0:r - 1]的数字都小于 [5]但是在右边,所以产生逆序对
  12. // 3.[6] < [7], r 右移
  13. // 4.[7] l 右移, 产生逆序对
  14. if (nums.length === 0) return 0
  15. let res = 0
  16. const merge = (arr, left, right, mid) => {
  17. const a = arr.slice(left, mid + 1)
  18. const b = arr.slice(mid + 1, right + 1)
  19. let l = 0, r = 0, k = left
  20. while (l < a.length && r < b.length) {
  21. if (a[l] <= b[r]) {
  22. arr[k] = a[l]
  23. k++
  24. l++
  25. res += r
  26. } else {
  27. arr[k] = b[r]
  28. k++
  29. r++
  30. }
  31. }
  32. while (l < a.length) {
  33. arr[k] = a[l]
  34. k++
  35. l++
  36. res += r
  37. }
  38. while (r < b.length) {
  39. arr[k] = b[r]
  40. k++
  41. r++
  42. }
  43. }
  44. const mergeSort = (arr, l, r) => {
  45. if (l === r) {
  46. return
  47. }
  48. const m = l + ((r - l) >> 1)
  49. mergeSort(arr, l, m)
  50. mergeSort(arr, m + 1, r)
  51. merge(arr, l, r, m)
  52. }
  53. mergeSort(nums, 0, nums.length - 1)
  54. return res
  55. };