归并排序
归并排序,常用于计算数组中的逆序对数量
@Test
public void Test_873(){
int[] arr = {2,3,4,1,-8,4,2,10};
int n = arr.length;
int[] help = new int[n];
MergeSort(0, n-1, help, arr);
System.out.println(Arrays.toString(arr));
}
public void MergeSort(int l, int r, int[] help, int[] nums){
if(l == r)
return ;
int mid = l + (r-l)/2;
// 递归的分割左右两部分
MergeSort(l, mid, help, nums);
MergeSort(mid+1, r, help, nums);
// 利用辅助数组进行排序
for(int i=l;i<=r;i++){
help[i] = nums[i];
}
// 合并分割的小区间,本质是合并两个有序数组,即[l,mid]和[mid+1, r]两个有序区间
int left = l, right = mid+1;
for(int i=l;i<=r;i++){
if(left == mid+1){ // [l,mid]的数组已经遍历完了
nums[i] = help[right++];
}else if(right == r+1){ // [mid+1, r]的数组已经遍历完了
nums[i] = help[left++];
}else if(help[left] <= help[right]){
nums[i] = help[left++];
}else if(help[left] > help[right]){
nums[i] = help[right++];
}
}
}
当我们需要统计数组中的逆序对时,只需要在合并两个有序数组时,统计逆序对的数量即可
完整代码如下:
public int mergeSort(int l, int r, int[] help){
if(l == r) return 0;
int mid = l+(r-l)/2;
int res = mergeSort(l, mid, help) + mergeSort(mid+1, r,help);
// 利用辅助数组对[l,r]区间内进行排序
for(int i=l;i<=r;i++){
help[i] = nums[i];
}
// 排序的过程相当于是合并两个有序数组[l, mid] [mid, r]
int left = l, right = mid+1;
for(int i=l;i<=r;i++){
if(left == mid+1){
nums[i] = help[right++];
}else if(right == r+1){
nums[i] = help[left++];
}else if(help[left] <= help[right]){
nums[i] = help[left++];
}else if(help[left] > help[right]){
res += mid - left+1;
nums[i] = help[right++];
}
}
return res;
}