牛客剑指Offer面试题51:数组中的逆序对(归并排序,待复习递归思想)

题目描述

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

数据范围:

对于%50的数据,size<=10^4

对于%75的数据,size<=10^5

对于%100的数据,size<=2*10^5

示例1
输入
复制
1,2,3,4,5,6,7,0
输出
复制
7

思路

利用归并排序思想,不断分别递归调用划分一半的函数,将整个数组划分为左右两半,先不断递归划分左边数组至单个元素,逐层返回上级,

注意:
1.右数组起始索引为start + Index + 1
2.牛客已知题干与书上不同,要求%100000007, 需使用long long 类型数?
C++Primer中写道:如果数值超过了int的表示范围,则用long long.(实际应用中,short显得太小,而long和int一般有一样的尺寸)
3.函数传入参数时copy和data互换?
4.归并算法实现使用递归的理解可以参考Python数据结构笔记及视频

代码

class Solution {
public:
    int InversePairs(vector<int> data) {
        //判断有效性
        if(data.empty())
            return 0;
        int length = data.size();
        //创建辅助数组
        vector<int> copy;
        //拷贝data内元素至copy中
        for(int i = 0; i < length; ++i)
            copy.push_back(data[i]);
        
        long long totalNum = InversePairsCore(data, copy, 0, length - 1);
        return totalNum%1000000007;
    }
    
    
    long long InversePairsCore(vector<int>& data, vector<int>& copy, int start, int end)
    {
        //划分至只有一个元素
        if(start == end)
        {
            copy[start] = data[start];
            return 0;
        }
        //用游标将数组划分为2
        int Index = (end - start) / 2;
        
        long long left = InversePairsCore(copy, data, start, start + Index);
        long long right = InversePairsCore(copy, data,start + Index + 1, end);
        //辅助数组游标指向末尾
        int indexOfCopy = end;
        //声明两个游标分别指向每个左右数组的末尾元素
        int i = start + Index;
        int j = end;
        //声明变量记录逆序对数量
        long long count = 0;
        //当左右数组内元素未遍历完
        while(i >= start && j >= start + Index + 1)
        {
            //如果左数组末尾元素大于右数组末尾元素
            if(data[i] > data[j])
            {
                copy[indexOfCopy--] = data[i--];
                //此时右数组所有元素都与左数组游标所指元素构成逆序对,数量为右数组元素数量
                count += (j - start - Index);
            }
            //左数组末尾元素小于右数组末尾元素
            else
            {
                //将右数组末尾元素拷贝至辅助数组,并前移两个游标
                copy[indexOfCopy--] = data[j--];
            }
        }
        //如右(左)数组已复制完毕,但左(右)数组内还有元素,则复制剩余元素到辅助数组中
        //如果右子数组拷贝完毕,则继续拷贝剩余左子数组
        for(; i >= start ; --i)
            copy[indexOfCopy--] = data[i];
        //如果左子数组拷贝完毕,则继续拷贝剩余右子数组
        for(; j >= start + Index + 1; --j)
            copy[indexOfCopy--] = data[j];
        return count + left + right;
    }
};
发布了65 篇原创文章 · 获赞 0 · 访问量 2035

猜你喜欢

转载自blog.csdn.net/ljmiiianng/article/details/103792834
今日推荐