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:
Given nums = [5, 2, 6, 1]
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.
Return the array [2, 1, 1, 0].
这个问题可以归纳为一个排序问题。因为统计的是每个数右边的数组,所以自然从尾部开始考虑。而这样的话,就相当于向一个数组中按照从小到大的顺序插入数据,并返回该数据的下标。而插入数据的位置通过二分搜索方法进行,效率会比较高。
代码如下:
class Solution {
public:
vector<int> countSmaller(vector<int>& nums)
{
vector<int> a;
vector<int> result;
int size = nums.size();
for(int i=size-1;i>=0;--i)
result.insert(result.begin(),putin(nums[i],a));
return result;
}
int putin(int target,vector<int> & a)
{
if(!a.size())
{
a.push_back(target);
return 0;
}
int lo = 0,hi = a.size()-1;
int size = a.size();
while(lo <= hi)
{
int mid = lo+(hi-lo)/2;
if(a[mid] < target)
{
if(mid+1 == size)
{
a.push_back(target);
return size;
}
else if(a[mid+1] > target)
{
a.insert(a.begin()+mid+1,target);
return mid+1;
}
lo = mid+1;
}
else
{
if(!mid)
{
a.insert(a.begin(),target);
return 0;
}
else if(a[mid-1] < target)
{
a.insert(a.begin()+mid,target);
return mid;
}
hi = mid-1;
}
}
return -1;
}
};