问题:
给定一个数组,从左向右遍历数组每一个元素,
对每一个元素,记录,其右边比他小的元素个数到res数组中。
求res数组。
Example: Input: [5,2,6,1] Output: [2,1,1,0] Explanation: To the right of 5 there are 2 smaller elements (2 and 1). To the right of 2 there is only 1 smaller element (1). To the right of 6 there is 1 smaller element (1). To the right of 1 there is 0 smaller element.
解法:
解法一:FenwickTree
使用以下辅助变量:
- sortedNums:ftree,对给定数组,进行排序。
- FenwickTree:sortnums,记录到目前为止,某个排序位置X以前,共有多少元素。(即<=X的元素有多少个)
由于本题,要求的是某元素以右的更小元素个数。
我们从后往前进行遍历,即可利用已经记录的结果。
最后将得到的res进行反转reverse即可。
代码参考:
1 class FenwickTree { 2 public: 3 FenwickTree(int n):tree(n+1,0) {} 4 void update(int i, int delta) { 5 while(i<tree.size()){ 6 tree[i]+=delta; 7 i+=lowbit(i); 8 } 9 } 10 int preSum(int i){ 11 int sum=0; 12 while(i>0){ 13 sum+=tree[i]; 14 i-=lowbit(i); 15 } 16 return sum; 17 } 18 private: 19 vector<int> tree; 20 int lowbit(int x) { 21 return x&(-x); 22 } 23 }; 24 class Solution { 25 public: 26 vector<int> countSmaller(vector<int>& nums) { 27 vector<int> res; 28 FenwickTree ftree(nums.size()); 29 vector<int> sortnums(nums); 30 sort(sortnums.begin(), sortnums.end()); 31 for(int i=nums.size()-1; i>=0; i--){ 32 int pos = distance(sortnums.begin(), lower_bound(sortnums.begin(), sortnums.end(), nums[i])); 33 res.push_back(ftree.preSum(pos)); 34 ftree.update(pos+1, 1); 35 } 36 reverse(res.begin(), res.end()); 37 return res; 38 } 39 };
解法二:mergeSort
⚠️ 注意:由于mergeSort会打乱原来数组的顺序,在mergeSort过程中,要同时保存计数结果,
需要同时将原来的index位置,存入,使得在mergeSort的过程中,也能找到原来的位置,进行计数。
- vector<vector<int>> numspos(nums.size(), vector<int>(2,0));
1 class Solution { 2 public: 3 vector<int> countSmaller(vector<int>& nums) { 4 vector<int> res(nums.size(), 0); 5 vector<vector<int>> numspos(nums.size(), vector<int>(2,0)); 6 for(int i=0; i<nums.size(); i++){ 7 numspos[i][0]=nums[i]; 8 numspos[i][1]=i; 9 } 10 mergeSort(numspos, res, 0, nums.size()-1); 11 return res; 12 } 13 void mergeSort(vector<vector<int>>& nums, vector<int>& res, int start, int end) { 14 if(end<=start) return; 15 int mid = start + (end - start) / 2; 16 mergeSort(nums, res, start, mid); 17 mergeSort(nums, res, mid+1, end); 18 merge(nums, res, start, mid, end); 19 } 20 void merge(vector<vector<int>>& nums, vector<int>& res, int start, int mid, int end) { 21 int p=start, q=mid+1, t=0; 22 vector<vector<int>> tmp(end-start+1, vector<int>(2,0)); 23 for(p=start; p<=mid; p++){ 24 while(q<=end && nums[p][0]>nums[q][0]){ 25 q++; 26 } 27 res[nums[p][1]]+=(q-1-mid); 28 } 29 p=start, q=mid+1; 30 while(p<=mid && q<=end){ 31 if(nums[p][0]>nums[q][0]){ 32 tmp[t++]=nums[q++]; 33 } else { 34 tmp[t++]=nums[p++]; 35 } 36 } 37 while(p<=mid){ 38 tmp[t++]=nums[p++]; 39 } 40 while(q<=end){ 41 tmp[t++]=nums[q++]; 42 } 43 copy(tmp.begin(), tmp.end(), nums.begin()+start); 44 } 45 };