• [剑指offer]51-数组中的逆序对(归并排序)


    题目链接

    https://www.nowcoder.com/questionTerminal/96bd6684e04a44eb80e6a68efc0ec6c5

    题意

    在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007。题目保证输入的数组中没有的相同的数字。

    解题思路

    在归并排序的过程中计逆序对。时间复杂度O(nlogn),空间复杂度O(n)。

    • 将数组从中间分成前后两个数组(递归到只有一个数据项)。注意数组都是含该数组首尾坐标元素的。
    • 然后合并并排序两个数组,排序结果在copy数组。具体地,i、j指针从两个数组后向前遍历,将大的拷贝到copy数组(copy数组从后往前填)。最后剩下的数组的剩下的部分一并拷贝到copy数组
    • 在合并过程中计逆序对,若i指向的元素大于j,则count+=j-mid;即mid+1到j的元素都比i指向的元素小。
    • 最终返回的count是两个数组内部的逆序对 + 合并过程中的逆序对数(即上一条)。

    注意

    • 每次递归传参copy和array换位置(滚动数组)。保证(左右子数组返回后)开始时data[l,mid]和data[mid+1,r]内部有序,结束时copy[l,r]内部有序。
    • size_t 是>=0 所以当i=0,i--,i会等于一个较大正数而不是-1,仍满足while(i>=l),使得程序错误。
    • cnt+=(j-mid)%1000000007应改为cnt=(cnt+(j-mid))%1000000007

    代码

    class Solution {
    public:
        int InversePairs(vector<int> data) {
            int cnt=0;
            if(!data.empty()){
                vector<int> copy;
                for(auto it=data.begin();it!=data.end();++it){
                    copy.push_back(*it);
                }
                cnt=inversePairCnt(data,copy,0,data.size()-1);
            }
            return cnt;
        }
    private:
        int inversePairCnt(vector<int>& data,vector<int>& copy,int l,int r){
            if(l==r){
                return 0;
            }
            int mid=(l+r)>>1;
            int leftCnt=inversePairCnt(copy,data,l,mid);
            int rightCnt=inversePairCnt(copy,data,mid+1,r);
            //开始:此时data[l,mid]和data[mid+1,r]内部有序,copy[l,mid]和copy[mid+1,r]内部无序
            
            int i=mid;
            int j=r;
            int copyIndex=r;
            int cnt=0;
            while(i>=l&&j>mid){
                if(data[j]>data[i]){
                    copy[copyIndex--]=data[j--];
                }
                else{
                    cnt=(cnt+(j-mid))%1000000007;//
                    copy[copyIndex--]=data[i--];
                }
            }
            while(i>=l){//
                copy[copyIndex--]=data[i--];
            }
            while(j>mid){
                copy[copyIndex--]=data[j--];
            }
            //结束:此时copy[l,r]内部有序,data[l,r]内部无序
            return (leftCnt+rightCnt+cnt)%1000000007;
        }
    };
    
    
  • 相关阅读:
    八、Docker+RabbitMQ
    Spring.Net学习笔记一(IOC第一个实例)
    快速搞懂 SQL Server 的锁定和阻塞
    JQuery.Ajax()的data参数类型
    常用开源介绍
    AutoMapper简明教程(学习笔记)
    面向.Net程序员的前端优化
    --数组元素插入有两种方式
    JQuery源码分析-02正则表达式-RegExp-常用正则表达式
    关于ASP.NET MVC的Filter小记
  • 原文地址:https://www.cnblogs.com/coding-gaga/p/10545067.html
Copyright © 2020-2023  润新知