315. Count of Smaller Numbers After Self(二分或者算法导论中的归并求逆序数对)
作者:互联网
You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i]
is the number of smaller elements to the right of nums[i]
.
Example 1:
Input: nums = [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.
Constraints:
0 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
class Solution { public: vector<int> countSmaller(vector<int>& nums) { vector<int> res(nums.size(),0); //从右向左,将数组有序插入tmp.利用二分查找确定当前数右边比它小的数的个数 vector<int> tmp; for(int i=nums.size()-1;i>=0;i--){ int left = 0,right=tmp.size()-1; //找第一个大于等于当前数的位置。插入其中 while(left <= right){ int mid = left+(right-left)/2; if(tmp[mid] < nums[i]) left = mid+1; else right = mid-1; } //最后返回的位置是left res[i]=left; //插入nums[i] tmp.insert(tmp.begin()+left,nums[i]); } return res; } };
//归并:先引入逆序数;不同于逆序数对:
res[nums[i].second] += (j-mid-1);
这个里面坑比较多
class Solution { public: //法二:利用归并排序求逆序对数的方法 //https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/submissions/ vector<int> countSmaller(vector<int>& nums) { int n=nums.size(); vector<int> res(n,0); if(n==0 || n==1) return res; vector<pair<int,int>> tmp(n,pair<int,int>{0,0}); vector<pair<int,int>> idx; for(int i=0;i<n;i++){ idx.push_back(make_pair(nums[i],i)); } mergesort(idx,tmp,0,n-1,res); return res; } //merge的过程将left到right有序重新存入nums.归并nums[left,mid],nums[mid+1,right] void merge(vector<pair<int,int>>& nums,vector<pair<int,int>>& tmp,int left,int mid,int right,vector<int>& res) { int i=left,j=mid+1,k=left; for(;i<=mid&&j<=right;){ if(nums[i].first<=nums[j].first){ //不同于算整个数组逆序数 //这里的i不是之前的i。归并后数字的位置被改变了.所以利用pari记录nums[i]原始位置 //res[i] += (j-mid-1); res[nums[i].second] += (j-mid-1); tmp[k++] = nums[i++]; }else{ tmp[k++] = nums[j++]; } } //还有未归并完成的 while(i<=mid){ //先计算res res[nums[i].second] += (j-mid-1); tmp[k++]=nums[i++]; } while(j<=right){ tmp[k++]=nums[j++]; } //将tmp重新放入nums,那么nums[left,right]即有序了 for(int i=left;i<=right;i++){ nums[i] = tmp[i]; } return; } //归并排序 void mergesort(vector<pair<int,int>>& nums,vector<pair<int,int>>& tmp,int left,int right,vector<int>& res) { if(left < right){ int mid = left+(right-left)/2; mergesort(nums,tmp,left,mid,res); mergesort(nums,tmp,mid+1,right,res); //合并nums[left,mid] nums[mid+1,right] merge(nums,tmp,left,mid,right,res); } return; } };
标签:Count,Smaller,nums,int,res,Self,vector,right,left 来源: https://www.cnblogs.com/wsw-seu/p/13976049.html