剑指offer:数组中的逆序对

题目描述:

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

思路:

方法1:最直观的方法,顺序扫描数组,每扫描到一个数字,再顺序扫描其后的每个数字,如果后面的数字比当前数字小,则组成一个逆序对。这种方法需要两层循环,O(n^2)的复杂度。

方法2:借鉴归并排序的思路

先把数组分隔为子数组,统计子数组内部的逆序对的数目,然后再统计两个相邻子数组之间的逆序对的数目。

注意:

a. 调用InversePairsCore时,因为要把上一次排好序的结果做合并,所以data和count需要交换,copy中的数组是排好序的,data是用来做合并的,也就是上一步在copy中排好的子数组,下一步要作为data进行合并操作放入copy中,如此交替,最后data和copy中的数字完全一样。

b. 因为在算子数组的count过程中可能就超过1000000007溢出了,所以对于每次count增加之后都要对1000000007取模。

(刚开始只在最后一步返回count的时候取模了,case通过率只有50%)

参考代码:

在线测试

https://www.nowcoder.com/practice/96bd6684e04a44eb80e6a68efc0ec6c5?tpId=13&tqId=11188&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

AC代码

方法1:case通过率50%,对于很大的数组时间复杂度过高

class Solution {
public:
    int InversePairs(vector<int> data) {
        if(data.empty() || data.size()<2)
            return 0;
        int p=0;
        for(int i=0; i<data.size();i++)
        {
            for(int j=i+1;j<data.size();j++)
            {
                if(data[j]<data[i])
                    p++;
            }
        }
        p=p%1000000007;
        return p;
    }
};

方法2:

class Solution {
public:
    int InversePairs(vector<int> data) {
        if(data.empty()||data.size()<2)
            return 0;
        vector<int> copy(data);
        int count = InversePairsCore(data,copy,0,data.size()-1);
        return count%1000000007;
    }
    int InversePairsCore(vector<int> &data,vector<int> &copy,int start,int end)
    {
        if(start==end)
        {
            copy[start]=data[start];
            return 0;
        }
        int length=(end-start)/2;
        int left=InversePairsCore(copy,data,start,start+length);
        int right=InversePairsCore(copy,data,start+length+1,end);
        int p1=start+length;
        int p2=end;
        int p3=end;
        int count=0;
        while(p1>=start && p2>=start+length+1)
        {
            if(data[p1]>data[p2])
            {
                copy[p3--]=data[p1--];
                count = count + p2 - (start+length);
                count = count%1000000007;
            }
            else
            {
                copy[p3--]=data[p2--];
            }
        }
        while(p1>=start)
        {
            copy[p3--]=data[p1--];
        }
        while(p2>=start+length+1)
        {
            copy[p3--]=data[p2--];
        }
        return (left+right+count)%1000000007;
    }
};

猜你喜欢

转载自blog.csdn.net/u012991043/article/details/81489707