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
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
复制代码

 

posted on   itdef  阅读(297)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示