数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
这可能是我最近几天最大的收获。
此题加深了我对归并排序的理解,从过程到时间复杂度,空间复杂度。我还需要专门研究。下面先记录此题:
1、归并排序实现,数组分割与合并,递归。
2、在合并过程中,前数组与后数组不断取小者填入缓存,然后将缓存copy到数组中。
3、逆序数对的统计便发生在第二步,取后者的时候,是不是就代表着前者中现有的剩余数字都比此时要取得数字大,即构成逆序对。
Reference:
白话经典算法系列之五 归并排序的实现
http://blog.youkuaiyun.com/morewindows/article/details/6678165/
白话经典算法系列之九 从归并排序到数列的逆序数对(微软笔试题)
http://blog.youkuaiyun.com/morewindows/article/details/8029996
class Solution {
public:
int InversePairs(vector<int> data) {
if(data.empty()) return 0;
int sz=data.size();
vector<int> temp(sz);
mergeSort(data,temp,0,sz-1);
return count%1000000007 ;
}
/*归并排序:不断分割,最小时开始合并。
*一定要有序才能正确计算。
*逆序数对:当取后者数时,前者数剩余个数便是此数的逆序对个数
*/
private:
//分割
void mergeSort(vector<int> &data,vector<int> &temp,int beg,int end){
if(beg<end){
int mid=(beg+end)/2;
mergeSort(data,temp,beg,mid);
mergeSort(data,temp,mid+1,end);
mergeArray(data,temp,beg,mid,end);
}
}
//合并
void mergeArray(vector<int> &data,vector<int> &temp,int beg,int mid,int end){
int f1{beg},f2{mid+1},f{beg};
while(f1<=mid&&f2<=end){
if(data[f1]<data[f2]){
temp[f++]=data[f1++];
}
else{
temp[f++]=data[f2++];
count+=(mid-f1+1);
}
}
while(f1<=mid){
temp[f++]=data[f1++];
}
while(f2<=end){
temp[f++]=data[f2++];
}
for(int i=beg,j=beg;i<=end;++i,++j){
data[i]=temp[j];
}
}
long long count=0;
};