一、利用归并排序求小和
public class MergeSortSmallSum {
public static void main(String[] args) {
int[] arr = {1, 3, 4, 2, 5};
System.out.println(mergeSort(arr, 0, arr.length - 1));
}
/**
* 返回在l到r上产生的小和
* @param arr
* @param l
* @param r
* @return
* (l+r)/2 l+(r-l)/2
* a/2 = a >> 1
*/
public static int mergeSort(int[] arr, int l, int r) {
if (l == r) {
return 0;
}
//int mid = (l + r) / 2;
int mid = l + ((r - l) >> 1);
// 左侧,右侧 产生的小和加上左右两侧整体产生的小和
return mergeSort(arr, l, mid)
+ mergeSort(arr, mid + 1, r)
+ merge(arr, l, mid, r);
}
public static int merge(int[] arr, int l, int mid, int r) {
int[] help = new int[r - l + 1];
int i = 0;
int p1 = l;
int p2 = mid + 1;
int res = 0;
while (p1 <= mid && p2 <= r) {
res += arr[p1] < arr[p2] ? arr[p1] * (r - p2 + 1) : 0;
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= mid) {
help[i++] = arr[p1++];
}
while (p2 <= r){
help[i++] = arr[p2++];
}
for (i=0 ; i < help.length; i++) {
arr[l+i] = help[i];
}
return res;
}
}
二、利用归并排序求逆序对
逆序对问题:在一个数组中,左边的数如果比右边的数大,则折两个数构成一个逆序对,请打印所有逆序对
/**
* @auther Mr.Liao
* @date 2019/11/6 16:46
* 在一个数组中,左边的数如果比右边的数大,则这两个数构成一个逆序对,请打印所有逆序对。
* 9, 3, 8, 1
* 93 98 91 31 81
*/
public class MergeSort_nixudui {
static int count = 0;
public static void main(String[] args) {
int[] arr = {9, 3, 8, 1};
sortProcess(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
System.out.println(count);
}
public static void sortProcess(int[] arr, int l, int r) {
if (l == r) {
return;
}
int mid = (l + r) / 2;
// 左边归并排序
sortProcess(arr, l, mid);
// 右边归并排序
sortProcess(arr, mid + 1, r);
merge(arr, l, mid, r);
}
public static void merge(int[] arr, int l, int mid, int r) {
int[] help = new int[r - l + 1];
int i = 0;
int p1 = l;
int p2 = mid + 1;
// 都没有到头,取出来比较
while (p1 <= mid && p2 <= r) {
if (arr[p1] > arr[p2]) {
help[i++] = arr[p2++];
// 因为如果arr[p1]此时比右数组的当前元素arr[p2]大,
// 那么左数组中arr[p1]后面的元素就都比arr[p2]大
count += mid - p1 + 1;
} else {
help[i++] = arr[p1++];
}
}
// 右边的到 r位置了
while (p1 <= mid) {
help[i++] = arr[p1++];
}
// 左边的到 mid位置了了
while (p2 <= r) {
help[i++] = arr[p2++];
}
for (i = 0; i < help.length; i++) {
arr[l + i] = help[i];
}
}
}