题目描述:

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


示例 1:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof

知识点:

  • 归并排序

解题思路:

  • 这道题给我们一个数组要我们求其中逆序对的个数,我们采用类似于归并排序的思路来解决这道题
  • 具体步骤为,我们首先需要让指针指向相邻的两个数字来划分出两个数组
  • 我们让两个指针分别指向这两个数组的最右端
  • 判断最右端两个数字的大小,将较大的那个放在数组中靠后的位置上
  • 这样递归下来我们可以发现,左右两个数组都是按照升序排列的,如果左边数组最右边的元素大于右边数组最右端的元素那么,左边数组最右端的元素将大于右边数组中所有的数
  • 如图所示,如果实在无法理解可以边看代码,边看图,以7,5,6,4为例理解

数组中的逆序对.png

解题代码:

  1. var reversePairs = function(nums) {
  2. return mergeSort(nums,0,nums.length-1,[]);
  3. function mergeSort(array,left,right,temp){
  4. if(left < right) {
  5. // 1.让指针指向相邻的两个元素,同时判断这两个元素是不是逆序对
  6. let mid = (left + right) >> 1;
  7. let l = mergeSort(array,left,mid,temp);
  8. let r = mergeSort(array, mid+1,right,temp);
  9. // 2.判断左右指针所指元素中一共有多少对逆序对
  10. let res = merge(array,left,right,mid,temp);
  11. return l + r + res;
  12. }else {
  13. return 0;
  14. }
  15. }
  16. function merge(array,left,right,mid,temp){
  17. let leftIndex = mid;
  18. let rightIndex = right;
  19. let tempIndex = right - left;
  20. let count = 0;
  21. while(leftIndex >= left && rightIndex > mid){
  22. console.log(array[leftIndex],array[rightIndex])
  23. if(array[leftIndex] > array[rightIndex]){
  24. count += (rightIndex - mid);
  25. temp[tempIndex--] = array[leftIndex--];
  26. }else {
  27. temp[tempIndex--] = array[rightIndex--];
  28. }
  29. }
  30. while(leftIndex >= left) {
  31. temp[tempIndex--] = array[leftIndex--];
  32. }
  33. while(rightIndex > mid) {
  34. temp[tempIndex--] = array[rightIndex--];
  35. }
  36. tempIndex = 0;
  37. for(let i = left;i<=right;i++) {
  38. array[i] = temp[tempIndex++]
  39. }
  40. return count;
  41. }
  42. };