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