493. Reverse Pairs

问题:

给定一个数组nums,若 i < j, nums[i] > 2*nums[j],则称这一对 i,j为important reverse pair

求给定数组中,有多少组important reverse pair。

Example1:
Input: [1,3,2,3,1]
Output: 2

Example2:
Input: [2,4,3,5,1]
Output: 3

Note:
The length of the given array will not exceed 50,000.
All the numbers in the input array are in the range of 32-bit integer.

  

解法:

解法一:FenwickTree

方针:遍历数组,对每一个新遍历到的数nums[j],看已经遍历过的数里面,是否存在满足要求的nums[i](nums[i] > 2*nums[j])

我们使用FenwickTree来记录到目前为止,满足要求的nums[i]总共有多少个。

每遍历一个数,update到FenwickTree中。

presum来得到满足要求的nums[i]的个数。

这里,我们需要使用辅助数组,sortnums来存放经过排序后的nums

使用FenwickTree来对应sortnums的计数。(相同index下)

具体做法:

每遍历一个nums[j]

在sortnums中找到<=2*nums[j]的index

那么在FenwickTree中,到目前为止所有个数 0~index的个数 = >2*nums[j]的个数

在sortnums中找到nums[j]的index

更新到FenwickTree.update(index,1)

⚠️ 注意:这里对于重复相同的元素,index可能会重复,但是没关系,我们要求的是计数个数,(不需要index一一对应)直接使用update方法更新增加delta=1即可。

代码参考:

 1 class FenwickTree {
 2 public:
 3     FenwickTree(int n):preSum(n+1, 0){}
 4     void update(int i, int delta){
 5         while(i<preSum.size()){
 6             preSum[i]+=delta;
 7             i+=lowbit(i);
 8         }
 9     }
10     int getPreSum(int i){
11         int sum=0;
12         while(i>0){
13             sum+=preSum[i];
14             i-=lowbit(i);
15         }
16         return sum;
17     }
18 private:
19     vector<int> preSum;
20     int lowbit(int x){
21         return x&(-x);
22     }
23 };
24 
25 class Solution {
26 public:
27     int reversePairs(vector<int>& nums) {
28         FenwickTree tree(nums.size());
29         vector<int> sortnums(nums);
30         sort(sortnums.begin(), sortnums.end());
31         int res=0;
32         for(int i=0; i<nums.size(); i++){
33             //对每一个j,前面遍历过的每个i,是否有满足条件nums[i] > 2*nums[j]的
34             //找大于2*nums[j]的位置
35             //sort从小到大,先找<=2*nums[j]的位置
36             int dislower=distance(sortnums.begin(), upper_bound(sortnums.begin(),sortnums.end(),(long long)2*nums[i]));
37             res+=(tree.getPreSum(nums.size())-tree.getPreSum(dislower));
38             //将遍历过的元素更新到tree
39             int pos_sorted_i=distance(sortnums.begin(), lower_bound(sortnums.begin(),sortnums.end(),nums[i]))+1;
40             tree.update(pos_sorted_i, 1);
41         }
42         return res;
43     }
44 };

解法二:

归并排序 merge Sort

在归并排序的合并两个有序数列过程中,追加一个判断,

  • if 左边的数>=2倍的右边的数:res+=左边剩下的数。
  • 左边下一个数

代码参考:

 1 class Solution {
 2 public:
 3     int reversePairs(vector<int>& nums) {
 4         int res=0;
 5         if(nums.size()==0) return 0;
 6         res = mergeSort(nums, 0, nums.size()-1);
 7         return res;
 8     }
 9     int mergeSort(vector<int>& nums, int start, int end) {
10         int res=0;
11         if (start==end) {
12             return 0;
13         }
14         int mid = start + (end - start) / 2;
15         res+=mergeSort(nums, start, mid);
16         res+=mergeSort(nums, mid+1, end);
17         res+=merge(nums, start, mid, end);
18         return res;
19     }
20     int merge(vector<int>& nums, int start, int mid, int end) {
21         int p = start, q = mid+1;
22         int res=0;
23         while(p<=mid && q<=end) {
24             if(nums[p] > (long long)2*nums[q]){
25                 res+=(mid-p+1);
26                 q++;
27             }else{
28                 p++;
29             }
30         }
31         
32         vector<int> a(end-start+1, 0);
33         p = start, q = mid+1;
34         int ai=0;
35         while(p<=mid && q<=end) {
36             if(nums[p] < nums[q]){
37                 a[ai]=nums[p];
38                 p++,ai++;
39             }else{
40                 a[ai]=nums[q];
41                 q++,ai++;                
42             }
43         }
44         while(p<=mid){
45             a[ai++]=nums[p++];
46         }
47         while(q<=end){
48             a[ai++]=nums[q++];
49         }
50         copy(a.begin(), a.end(), nums.begin()+start);
51         return res;
52     }
53 };
原文地址:https://www.cnblogs.com/habibah-chang/p/13419857.html