微软面试题: 剑指 Offer 51. 数组中的逆序对 出现次数:2

 

 具体可参考

https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solution/bao-li-jie-fa-fen-zhi-si-xiang-shu-zhuang-shu-zu-b/

代码如下:

 1 class Solution {
 2 public:
 3     vector<int> tmp;//归并排序的辅助数组
 4 
 5     int reversePairs(vector<int>& nums) {
 6         const int len = nums.size();
 7         if(len < 2) return 0;
 8         tmp.assign(len,0);
 9         return merge_sort(nums,0,len - 1);
10     }
11  
12     long long int merge_sort(vector<int>& nums,int l,int r)
13     {
14         if(l >= r)//归并排序递归出口
15         {
16             return 0;
17         }
18         int mid = l + (r - l)/2;//将区间一分为二
19         long long ans = merge_sort(nums,l,mid) + merge_sort(nums,mid + 1,r);//递归地求左右子数组的逆序对个数和
20         //剪枝优化: 子数组[l,r] 已经有序,横跨两个区间的逆序对个数为 0
21         if(nums[mid + 1] >= nums[mid])
22         {
23             return ans;
24         }
25         //计算 横跨左右区间的逆序对
26         int k = 0,i = l,j = mid + 1;
27         while(i <= mid && j <= r)
28         {
29             if(nums[i] <= nums[j])
30             {
31                 tmp[k++] = nums[i++];
32             }
33             else
34             { //执行上述递归之后,左右子数组都已经排好序
35               //此处,nums[i:mid] 都比nums[j] 大,都和num[j] 构成逆序对
36                 ans += (mid - i + 1);
37                 tmp[k++] = nums[j++];
38             }
39         }
40         //将左右区间未移动到tmp的继续移到tmp
41         while(i <= mid) tmp[k++] = nums[i++];
42         while(j <= r) tmp[k++] = nums[j++];
43         //将排序好的元素移回原数组,放在原来的区间上,然后nums[l:r]已经排序好了 
44         for(i = l,j = 0;i <= r; )
45         {
46             nums[i++] = tmp[j++];
47         }
48         return ans;
49     }
50 };

 

posted @ 2021-04-12 20:16  谁在写西加加  阅读(39)  评论(0编辑  收藏  举报