题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:
题目保证输入的数组中没有的相同的数字
数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5
示例1
输入
1,2,3,4,5,6,7,0
输出
7
思路:
使用归并排序+递归方式,需要注意的是,递归时需要对原空间和辅助空间进行轮换,每次传参的第二项都是辅助空间,用于记录最新排序结果,而递归回到上一层时,需要根据最新的局部排序结果来更新整体排序结果。
以代码为例,data是原空间而copy是辅助空间,第一次调用左右进入递归时,将copy作为原空间/data作为辅助空间,而当这一次递归结束时,data中的内容已经是最新的排序结果,在当前层可以被用于对比来写最新的排序结果copy,即data永远是次新的排序结果,copy是需要被重写和最新的。
总而言之,保证每次在合并时,用于对比的数组都是上一次递归完成后最新的排序结果
正确方法:
class Solution {
public:
int InversePairs(vector<int> data) {
if(data.empty())
return 0;
//int* copy = new int [data.size()];
vector<int> copy(data.begin(),data.end());
int count = InversePairs_merge(data,copy,0,data.size()-1);
return count;
}
int InversePairs_merge(vector<int>&data,vector<int>©,int start,int end){
if(start == end)
{
copy[start] == data[start];
return 0;
}
int len = (end - start)>>2;
int left = InversePairs_merge(copy,data,start,start+len); //copy和data换位
int right = InversePairs_merge(copy,data,start+len+1,end); //copy和data换位
int i = start+len;
int j = end;
int copyindex = end;
int count = 0;
while(i>=start && j>=start+len+1){
if(data[i]>data[j])
{
copy[copyindex--] = data[i--];
count += j-start-len;
if(count>=1000000007)
count %= 1000000007;
}
else
copy[copyindex--] = data[j--];
}
while(i>=start)
copy[copyindex--] = data[i--];
while(j>=start+len+1)
copy[copyindex--] = data[j--];
return (left+right+count)%1000000007;
}
};
根据剑指offer面试题51 写出一个递归的归并排序如下:
#include<iostream>
#include<algorithm>
#include<string.h>
void merge(int* a,int* b,int start,int mid,int end){
int i=start;
int j=mid+1;
int index = start;
while(i<=mid && j<=end){
if(a[i]<=a[j])
b[index++]=a[i++];
else
b[index++]=a[j++];
}
while(i<=mid)
b[index++]=a[i++];
while(j<=end)
b[index++]=b[j++];
}
void merge_sort(int* a,int* b,int start,int end){
if(start<end){
std::cout<<"before";
for(int i=0;i<9;i++)
std::cout<<b[i]<<' ';
std::cout<<std::endl;
int mid = (end-start)/2+start;
merge_sort(b,a,start,mid); //left sort,传入的是b,a 目的是用a记录最新的排序结果
merge_sort(b,a,mid+1,end);//right sort
merge(a,b,start,mid,end); //a作为上次调用获得的最新排序结果 作为对比依据 用b记录最新结果
std::cout<<"after ";
for(int i=0;i<9;i++)
std::cout<<b[i]<<' ';
std::cout<<std::endl;
}
}
int main(){
int a[9]={5,3,1,7,9,6,2,4,8};
int* b = new int [sizeof(a)/sizeof(int)];
memcpy(b,a,sizeof(a));
merge_sort(a,b,0,8);
std::cout<<"Final ";
for(int i=0;i<sizeof(a)/sizeof(int);i++)
std::cout<<b[i]<<' ';
return 0;
}
51题错误记录: 没有注意到辅助空间的轮换
class Solution {
public:
int InversePairs_merge(vector<int> data,int* list,int start,int end){
if(start==end){
list[start]=data[start];
return 0;
}
int len = (end-start)/2;
int left = InversePairs_merge(data,list,start,start+len);
int right = InversePairs_merge(data,list,start+len+1,end);
int i=start+len;
int j=end;
int copyindex = end;
int count = 0;
while(i>=start && j>=start+len+1){
if(data[i]>data[j])
{
list[copyindex--]=data[i--];
count += j-start-len;
}
else
list[copyindex--]=data[j--];
}
while(i>=start)
list[copyindex--]=data[i--];
while(j>=start+len+1)
list[copyindex--]=data[j--];
return count+left+right;
}
int InversePairs(vector<int> data) {
if(data.empty())
return 0;
int len = data.size();
int *list = new int[len];
for(int i=0;i<len;i++){
list[i]=data[i];
}
int count = InversePairs_merge(data,list,0,len-1);
delete []list;
return count;
}
};