問題描述:
在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數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);
//對data左半段和右半段的數據進行歸併排序,並統計逆序個數
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];
//data總的逆序對數:左半段內部逆序對數+右半段內部逆序對數+左右兩段間的逆序對數
return left+right+count;
}
};