Count the number of elements on the right that are less than the current element.
Given an integer array nums, return a new array counts as required. The array counts has this property: The value of counts [i] is the number of elements on the right of nums [i] that are less than nums [i].
Example:
Input: [5,2,6,1]
Output: [2,1,1,0]
Explanation:
On the right side of 5 there are 2 smaller elements (2 and 1).
On the right side of 2 there is only 1 smaller element (1).
On the right side of 6 there is 1 smaller element (1).
There are 0 smaller elements to the right of 1.
[ Link ]
Ideas
This question can use the idea of divide and conquer:
suppose the function can find the [l, r]
number of each number and the number on the right that is smaller than him.
Use mid to divide the array into two, then for the subscript i (i <= mid), you can The problem is broken down into:
- Find a number less than i in [l, mid]
- Find a number less than i in [mid + 1, r]
The former can be solved by recursion, recursively sorting the sub-arrays at the same time, the latter, find two subscripts in the ordered sequence to meet a certain size relationship, immediately think of the analogy [ reverse order pair problem ]
For the range of index i: [l ~ mid], in [mid + 1, r] j to the right in the first to find that nums[j]>=nums[i]
, because it is ascending, the mid+1 ~ j-1
subscripted number smaller than the nums [i], then the nums [i] The answer can be + = j- (mid + 1)
Note
For i, you need to enumerate in ascending order, because if you enumerate i in descending order, the decrease in nums [i] may cause the previous j to increase and the excluded answer is available again, so you should enumerate i in ascending order
Code
class Solution {
public:
vector<int> ans;
typedef struct p
{
int val, id;
p():val(0),id(0){}
p(int v, int i):val(v),id(i){}
}p;
static bool cmp(const p& p1, const p& p2){return p1.val<p2.val;}
void mer(vector<p>& nums, int l, int r)
{
if(l>=r || l<0 || r>=nums.size()) return;
int mid=(l+r)/2, j=mid+1;
mer(nums, l, mid), mer(nums, mid+1, r);
for(int i=l; i<=mid; i++)
{
while(j<=r && nums[i].val>nums[j].val) j++;
ans[nums[i].id] += j-(mid+1);
}
inplace_merge(nums.begin()+l, nums.begin()+mid+1, nums.begin()+r+1, cmp);
}
vector<int> countSmaller(vector<int>& nums)
{
ans.resize(nums.size());
vector<p> nu;
for(int i=0; i<nums.size(); i++)
nu.push_back(p(nums[i], i));
mer(nu, 0, nu.size()-1);
return ans;
}
};