【剑斩OFFER】算法的暴力美学——计算右侧小于当前元素的个数

一、题目原理

二、算法原理

使用归并排序算法(降序)+ 绑定数组下标 来解决这道题:

当 nums begin1 > nums begin2 时,end2 - begin2 + 1个数字小于nums begin1 ;例如 :7 > 4 ,那么 4 到 1 之间的数字都小于7;

因为在合并两个数组的时候会打乱各个数字的下标,根据题目要求我们是要在原数组的下标来判断每个数字的右边有多少个数字是小于当前数字的,所以我们要弄出两个数组来绑定下标:index1 和 index2 ,其中 index1 是保存原来数组的下标,而 index2 是保存合并数组后各个数字对应原来数组的下标,保证各个数字对应的下标不会乱,到时候再把 index2 里面的数字跟新到 index1 里面:

三、代码实现

cpp 复制代码
class Solution {
    vector<int> tmp;
    vector<int> index1;
    vector<int> index2;
    vector<int> ret;
public:
    vector<int> countSmaller(vector<int>& nums) {
        tmp.resize(nums.size());
        index1.resize(nums.size());
        ret.resize(nums.size());
        index2.resize(nums.size());
        for(int i = 0; i < nums.size();i++) index1[i] = i;
        Quicksort(0,nums.size()-1,nums,tmp);
        return ret;
    }

    void Quicksort(int l,int r,vector<int>& nums,vector<int>& tmp)
    {
        if(l >= r) return;
        
        int keyi = (r + l) >> 1;
        Quicksort(l,keyi,nums,tmp);//左边:【 l , keyi 】
        Quicksort(keyi + 1,r,nums,tmp);//右边:【keyi + 1,r 】

        int begin1 = l,end1 = keyi;//左边数组
        int begin2 = keyi + 1,end2 = r;//右边数组
        int index = l;//遍历起始点



        while(begin1 <= end1 && begin2 <= end2)//比较遍历
        {
            if(nums[begin1] > nums[begin2])
            {
                ret[index1[begin1]] += end2 - begin2 + 1;
                index2[index] = index1[begin1];//绑定下标
                tmp[index++] = nums[begin1++];
            }
            else 
            {
                index2[index] = index1[begin2];
                tmp[index++] = nums[begin2++];
            }
        }

        while(begin1 <= end1)
        {
            index2[index] = index1[begin1];
            tmp[index++] = nums[begin1++];//把左边剩余的数字放到 tmp
        }

        while(begin2 <= end2)
        {
            index2[index] = index1[begin2];
            tmp[index++] = nums[begin2++];//把右边剩余的数字放到 tmp
        }
        
        for(int i = l;i <= r;i++)
        {
            index1[i] = index2[i];
            nums[i] = tmp[i];//把 tmp 里面的数字放回到原数组 nums
        }
    }
};
相关推荐
TAN-90°-5 分钟前
Deep Learning for Computer Vision——Generative Models 2
人工智能·深度学习·神经网络·算法·目标检测·机器学习·计算机视觉
Rabitebla13 分钟前
【Linux系统编程】指令(三):创建、删除、复制、移动、看内容
linux·数据结构·c++·算法
圣保罗的大教堂1 小时前
leetcode 1401. 圆和矩形是否有重叠 中等
leetcode
qq_410194291 小时前
.NET 8.0 下基于 PaddleOCRSharp 的离线文字识别落地指南
算法·.net
Omics Pro1 小时前
1个月2轮融资!长寿虚拟细胞
数据库·人工智能·算法·机器学习·自然语言处理
residual_fan1 小时前
航空发动机故障诊断专用智能体(六):实际机队健康管理中的应用考量与展望
人工智能·算法·数据挖掘·数据分析
hansang_IR1 小时前
【讲解】CSP-S2026 第一轮初赛
c++·算法
hanlin031 小时前
刷题笔记:力扣第76题-最小覆盖子串
笔记·算法·leetcode
Zane19941 小时前
比较排序跑不出O(nlogn)是数学上证明过的,计数、桶、基数排序凭什么能绕开这堵墙
算法·排序算法
tiger8651 小时前
大语言模型面试和题解,梳理中国主流开源 LLM 系列的发展脉络、技术路线与工程取舍
人工智能·gpt·深度学习·算法·自然语言处理·面试·transformer