刷题-数组中逆序对数目

问题描述:

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

输入:1,2,3,4,5,6,7,0,输出:7.

解题思路:

思路1:暴力搜索

暴力搜索的方法思路很简单,就是从数组第一个数据开始遍历,逐个比较这个数据与其后数据的大小,记录逆序个数,该方法的时间复杂度为O(n^2)。

思路2:分析/归并排序思想

1、基于分治思想的归并排序:

给定一个无序数组,归并排序的思路如下图所示:

                                                                                      

将数组分成两个长度相同的子数组,再将每个子数组分成两个长度相同的子数组,直到不能分裂后,归并排序将相邻的两个子数组结合并排序,最后得到一个有序的。

2、统计逆序对数目:

class Solution {
public:
    int InversePairs(vector<int> data) {
       int length=data.size();
        if(length<=0)
            return 0;
       vector<int> copy; //排序的辅助数组
       for(int i=0;i<length;i++)
           copy.push_back(data[i]);
       long long count=InversePairsCore(data,copy,0,length-1);
       return count%1000000007;
    }
    long long InversePairsCore(vector<int> &data,vector<int> &copy,int start,int end){
        //指向相同元素,没有逆序,也就到了对并排序中最底层,
        if(start==end){
           copy[start]=data[start];
           return 0; //没有逆序对,返回0。
        }
        int length=(end-start)/2; //分裂
        // 使data左半段有序,并返回左半段逆序对的数目
        long long left=InversePairsCore(copy,data,start,start+length);
        // 使data右半段有序,并返回右半段逆序对的数目
        long long right=InversePairsCore(copy,data,start+length+1,end); 
        //归并排序,并统计逆序个数
        int i=start+length;
        int j=end;
        int indexcopy=end;
        long long count=0;
        while(i>=start&&j>=start+length+1){
            if(data[i]>data[j]){
                copy[indexcopy--]=data[i--];
                count=count+j-start-length;//count=count+j-(start+length+1)+1;
            }
            else{
                copy[indexcopy--]=data[j--];
            }
        }
        for(;i>=start;i--)
            copy[indexcopy--]=data[i];
        for(;j>=start+length+1;j--)
            copy[indexcopy--]=data[j];
        return left+right+count;
    }
};

 

                   

猜你喜欢

转载自blog.csdn.net/iea5357/article/details/106984646