问题:
给定一个数组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){ 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 };