LeetCode 315. 计算右侧小于当前元素的个数 树状数组 逆序对

地址 https://leetcode-cn.com/problems/count-of-smaller-numbers-after-self/

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

示例:

输入: [5,2,6,1]
输出: [2,1,1,0] 
解释:
5 的右侧有 2 个更小的元素 (21).
2 的右侧仅有 1 个更小的元素 (1).
6 的右侧有 1 个更小的元素 (1).
1 的右侧有 0 个更小的元素.

算法1
使用归并排序解决的逆序对问题
这里尝试使用树状数组解决
由于数字取值范围没有说,可能在0到INT_MAX之间取500个值
那么使用树状数组的空间就收到了限制,不得不使用离散化.
将0到INT_MAX的取值映射到0~ 500

这里使用哈希进行离散化,然后逆序将值输入树状数组
计算每个元素的右边比他大的数字有多少个

const int maxn = 3e6;
class Solution {
public:


int arr[maxn];
map<int, int> mp;
int k = 1;
int lowbit(int x) {
    return x & (-x);
}

int query(int x) {
    int res = 0;
    while (x >= 1) {
        res += arr[x];
        x -= lowbit(x);
    }

    return res;
}

void update(int x)
{
    while (x <= k) {
        arr[x] += 1;
        x += lowbit(x);
    }
}


vector<int> countSmaller(vector<int>& nums) {
    for (auto& e : nums) mp[e];

    map<int, int>::iterator it = mp.begin();

    for (; it != mp.end(); it++) {
        it->second = k++;
    }
    for (int i = 0; i < nums.size(); i++) {
        nums[i] = mp[nums[i]];
    }

    vector<int> res;
    for (int i = nums.size() - 1; i >= 0; i--)
    {
        res.push_back(query(nums[i] - 1));
        update(nums[i]);
    }
    reverse(res.begin(),res.end());
    return res;
}

};


作者:itdef
链接:https://www.acwing.com/solution/content/14614/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
阿里打赏 微信打赏
原文地址:https://www.cnblogs.com/itdef/p/13096361.html