问题描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数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> ©,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;
}
};