Leetcode-315. Calculate the number of elements on the right side 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 side of nums[i] that are less than nums[i].

Example:

Input: [5,2,6,1]
Output: [2,1,1,0]
Explanation: There are 2 smaller elements on the right side of 5 (2 and 1)
, and there is only 1 smaller element on the right side of 2 The element of (1)
6 has 1 smaller element to
the right (1) 1 has 0 smaller element to the right

Examine the application of the tree array.
The idea is to find the number of elements to the right of the current element and smaller than the current element. Obviously, the index of the left element is smaller than the right element. If the elements are sorted in ascending order, it is transformed into finding the number of elements to the left of the current element and greater than the index of the current element. This is the inverse number problem, which can be solved by a tree array.
Note that the final sequence must be sorted by index in ascending order, so that the sequence of elements obtained is the sequence of the original input.
Two cases are simulated:
case 1:

5 2 6 1
------------------
第一次排序前:
元素值:5 2 6 1
  下标:1 2 3 4
------------------
第一次排序后:
元素值:1 2 5 6
  下标:4 2 1 3
逆序数:0 1 2 1
------------------
第二次排序后:
元素值:5 2 6 1
  下标:1 2 3 4
逆序数:2 1 1 0

From the sequence before the first sorting, we can see that 5>2, but (5's index 1)<(2's index 3), for any a>b, there is (a's index)<(b's Index)
case 2:

5 2 6 2
------------------
第一次排序前:
元素值:5 2 6 2
  下标:1 2 3 4
------------------
第一次排序后:
元素值:2 2 5 6
  下标:2 4 1 3
逆序数:0 0 2 1
------------------
第二次排序后:
元素值:5 2 6 2
  下标:1 2 3 4
逆序数:2 0 1 0

Note that there may be cases where multiple element values ​​are equal. When the elements are equal for the first time, sort them in ascending order by index.

typedef struct node{
    
    
    int val;//元素的值
    int index;//元素的索引(从1开始)
    int cnt;//第一次排序后该元素前面的所有逆序数对
}Node;
/*
cmp1函数:
按元素值从小到大排序,元素值相同时按索引从小到大排序
*/
int cmp1(const void*a,const void*b){
    
    
    Node*x=(Node*)a;
    Node*y=(Node*)b;
    if(x->val!=y->val){
    
    
        return x->val-y->val;
    }
    else{
    
    
        return x->index-y->index;
    }
}
/*
cmp2函数:
直接按元素的索引从小到大排序
*/
int cmp2(const void*a,const void*b){
    
    
    Node*x=(Node*)a;
    Node*y=(Node*)b;
    return x->index-y->index;
}
class Solution {
    
    
private:
    Node*counts;
    int *tree;
    int len;
public:
    vector<int> countSmaller(vector<int>& nums) {
    
    
        len=nums.size();
        tree=new int[len+5];//leetcode上的代码风格不同于ACM
        counts=new Node[len+5];
        for(int i=1;i<=len;i++){
    
    
            tree[i]=0;//别忘了初始化
            counts[i].val=nums[i-1];
            counts[i].index=i;
        }
        qsort(counts+1,len,sizeof(counts[1]),cmp1);//第一次排序
        for(int i=1;i<=len;i++){
    
    
            update(counts[i].index);
            counts[i].cnt=i-query(counts[i].index);
        }
        qsort(counts+1,len,sizeof(counts[1]),cmp2);//第二次排序
        vector<int>ans;
        for(int i=1;i<=len;i++){
    
    
            ans.push_back(counts[i].cnt);
        }
        return ans;
    }
    int lowbit(int x){
    
    
        return x&(-x);
    }
    void update(int pos){
    
    //树状数组——更新
        int i=pos;
        while(i<=len){
    
    
            tree[i]++;
            i+=lowbit(i);
        }
    }
    int query(int pos){
    
    //树状数组——查询(求和)
        int ans=0;
        while(pos>0){
    
    
            ans+=tree[pos];
            pos-=lowbit(pos);
        }
        return ans;
    }
};

Guess you like

Origin blog.csdn.net/upc122/article/details/107735059