大家好,今天是星期一。在前面的归并排序中,我们讲了归并排序的基本概念,归并过程等,今天,我们来聊聊一些使用归并排序的常见面试题。一、小和问题1、题目说明:在一个数组中,每一个比当前数小的数左边的数之和称为数组的小和。找到给定数组的小和。2、例子:数组为:[1,3,4,2,5]1左边小于1的??数:3左边没有小于3的数:右边的数14左边小于4:1,32左边的数小于2数:15左边小于5的数:1,3,4,2,所以小和为1+(1+3)+1+(1+3+4+2)=163。思路:找出每个数右边大于当前数的数,(数*当前数)的累加和就是结果。这与归并排序有关。仔细想想,当左组和右组合并时,会比较数字的大小。这时候可以在右组中找到一个比左组中的当前数大的数。4、详细参考代码:/***小和问题:数组中,每个数左边小于当前数的数之和称为数组小和。要求时间复杂度O(N*logN)*@authorJava和算法学习:一周*/publicclassSmallSum{publicstaticintsmallSum(int[]arr){if(arr==null||arr.length<2){返回0;}返回过程(arr,0,arr.length-1);}privatestaticintprocess(int[]arr,intl,intr){if(l==r){返回0;}intmid=l+((r-l)>>1);returnprocess(arr,l,mid)+process(arr,mid+1,r)+merge(arr,l,mid,r);}privatestaticintmerge(int[]arr,intl,intmid,intr){int[]help=newint[r-l+1];int=0;intpL=l;intpR=mid+1;intres=0;while(pl<=mid&&pr<=r){//当当的数的数数时顺序比较,发现这里的代码就多了。唯一不同的是,//相等的时候,复制右组,因为如果要找右组比左组大的数,一定不能先复制左组,否则怎么找出数res+=arr[pL]aj,则表示ai和aj是一对逆对,求给定数组中逆对的个数。2.示例:3521049所有反向对为:(3,2),(3,1),(3,0),(5,2),(5,1),(5,0),(5,4),(2,1),(2,0),(1,0)。反向对数为10。3、思路:合并时,从右向左合并,(此时右组位置-中间位置的累加和)为反向对数。这与归并排序有什么关系?仔细想想。左组和右组合并的时候,会比较数字的大小,但是我要找的是右边那个小的,所以可以用从右到左的合并,同时,当处理相等,需要先复制右组,这样才能准确找出右组的小数。4、详细参考代码:/***逆序对问题:存在一个数组[a1,a2,a3,...an],对于数组中的任意两个元素ai和aj,若iaj,表示ai和aj是一对反向的。*查找给定数组中逆对的数量。**@authorJava和算法学习:星期一*/publicclassReversePair{publicstaticintreversePairNum(int[]arr){if(arr==null||arr.length<2){return0;cn处理t(,0,arr.length-1);}privatestaticintprocess(int[]arr,intl,intr){if(l==r){返回0;}}intmid=l-((r)>>1);返回过程(arr,l,mid)+过程(arr,mid+1,r)+合并(arr,l,mid,r);}privatestaticintmerge(int[]arr,intl,intmid,intr){//辅助数组int[]help=newint[r-l+1];//辅助下标,由于是从右向左合并,所以下标为数组的最大值inti=help.length-1;//同样,左边组中的第一个数字是midintpL=mid;//右组第一个数字是最后一个intpR=r;//倒序的对数=0;while(pL>=l&&pR>=(mid+1)){//找到右组中第一个小于左组的数,则当前满足要求的逆对数为(pR-(mid+1)+1)是(pR-mid)num+=arr[pL]>arr[pR]?(pR-中):0;//从右向左复制,右组的相等副本help[i--]=arr[pL]>arr[pR]?--];}}//左组和右组只有一个没有被复制,所以后面的两个循环只会执行其中一个while(pL>=l){help[i--]=arr[pL--];}}while(pR>mid){help[i--]=arr[pR--];}}//复制回原始数组for(intj=0;j