LeetCode: 315. Calculate the number of elements on the right that are less than the current element

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-1subscripted 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;
    }
};
Published 262 original articles · won 11 · 10 thousand views

Guess you like

Origin blog.csdn.net/weixin_44176696/article/details/105100069