315. 计算右侧小于当前元素的个数——归并排序

给你一个整数数组 nums ,按要求返回一个新数组 counts 。数组 counts 有该性质: counts[i] 的值是nums[i] 右侧小于 nums[i] 的元素的数量。

class Solution {
    vector<int> index;  //记录序号
    vector<int> temp;   //临时的数组
    vector<int> tempIndex;  //临时数组对应的序号
    vector<int> ans;    //答案
public:
    void merge(vector<int> & nums, int left, int mid, int right){
        int fir = left, sec = mid + 1, sorted = left;//不能出现写sorted = 1这种错误,这都是对数组的相对位置进行操作的
        while(fir <= mid && sec <= right){
            //如果第一个序列的小,那么加入到临时数组的sorted位置
            //并且把相应序号加入临时序号数组
            if(nums[fir] <= nums[sec]){
                temp[sorted] = nums[fir];
                tempIndex[sorted] = index[fir];
                //更新贡献值
                ans[index[fir]] += (sec - mid - 1);
                ++fir;
                ++sorted;
            }
            //同理第二个序列小,就拿第二个序列的出来加入
            else{
                temp[sorted] = nums[sec];
                tempIndex[sorted] = index[sec];
                ++sec;
                ++sorted;
            }
        }
        //如果第二个序列加入完了,就直接把第一个序列剩下没加入的一起加入到末尾
        while(fir <= mid){
            temp[sorted] = nums[fir];
            tempIndex[sorted] = index[fir];
            ans[index[fir]] += (sec - mid - 1);
            ++fir;
            ++sorted;
        }
        //如果第一个序列加入完了,就直接把第二个序列剩下没加入的一起加入到末尾
        while(sec <= right){
            temp[sorted] = nums[sec];
            tempIndex[sorted] = index[sec];
            ++sec;
            ++sorted;
        }
        //更新原序号与原数组
        //最初为什么不直接更新,是因为会影响到数组的顺序,导致数据混乱
        for(int i = left; i <= right; ++i){
            index[i] = tempIndex[i];
            nums[i] = temp[i];
        }
    }
    void mergeSort(vector<int>& nums, int left, int right){
        if(left >= right)
            return;
        int mid = (left + right) >> 1;//题目的数据不会溢出
        //往左分治
        mergeSort(nums, left, mid);
        //往右分治
        mergeSort(nums, mid + 1, right);
        merge(nums,left, mid, right);
    }
    vector<int> countSmaller(vector<int>& nums) {
        int n = nums.size();
        index.resize(n);
        temp.resize(n);
        tempIndex.resize(n);
        ans.resize(n);
        //构造序号数组
        for(int i = 0; i < n; ++i)
            index[i] = i;
        mergeSort(nums, 0, n - 1);
        return ans;
    }
};

Accepted
65/65 cases passed (316 ms)
Your runtime beats 40.23 % of cpp submissions
Your memory usage beats 56.35 % of cpp submissions (77.2 MB)

你可能感兴趣的:(力扣每日刷题,排序算法,leetcode,算法,c++,数据结构)