问题
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
分析
链接:https://www.nowcoder.com/questionTerminal/96bd6684e04a44eb80e6a68efc0ec6c5?f=discussion
来源:牛客网
归并排序的改进,把数据分成前后两个数组(递归分到每个数组仅有一个数据项),
合并数组,合并时,出现前面的数组值array[i]大于后面数组值array[j]时;则前面
数组array[i]~array[mid]都是大于array[j]的,count += mid+1 - i
代码
package DlinkedList;
import java.util.Arrays;
/**
* @Author Zhou jian
* @Date 2020 ${month} 2020/3/27 0027 14:45
* 采用归并的思想:
* 在治的过程中有前后数字大小的对比,此时就是统计逆序对的最佳时机
*/
public class Test2 {
int cnt;
public static void main(String[] args) {
int[] arr= {8,4,5,7,1,3,6,2};
Test2 test2 = new Test2();
test2.mergeSort(arr,0,arr.length-1,new int[arr.length]);
System.out.println(Arrays.toString(arr));
System.out.println(test2.cnt);
}
//归并排序
public void mergeSort(int[] arr,int left,int right,int[] temp){
if(left<right) {
int mid = (left + right) / 2;
//左递归
mergeSort(arr,left,mid,temp);
//右递归
mergeSort(arr,mid+1,right,temp);
merge(arr,left, mid,right,temp);
}
}
//合并
public void merge(int[] arr,int left,int mid,int right,int[] temp){
int t =0;//定义temp中的指针
int tempLeft=left;//定义左面指针
int tempRight = mid+1;//定义右面智者
while((tempLeft<=mid)&&(tempRight<=right)){
//前面数字大于后面数字
if((arr[tempLeft]>arr[tempRight])){
temp[t]=arr[tempRight];
tempRight++;
t++;
cnt +=mid-tempLeft+1;
cnt=cnt%1000000007;
}else{
temp[t]=arr[tempLeft];
tempLeft++;
t++;
}
}
while(tempLeft<=mid){
temp[t]=arr[tempLeft];
t++;
tempLeft++;
}
while(tempRight<=right){
temp[t]=arr[tempRight];
t++;
tempRight++;
}
tempLeft=left;
t=0;
for(;tempLeft<=right;){
arr[tempLeft++]=temp[t++];
}
}
}