最近在看左神的算法课,理解之后在此将代码记录下来
/**
* 归并排序
* @param arr 待排的数组
*/
private static void mergeSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
sortProcess(arr, 0, arr.length - 1);
}
/**
* 排序过程
* @param arr 待排子数组
* @param l 子数组开始位置
* @param r 子数组结束位置
*/
private static void sortProcess(int[] arr, int l, int r) {
if (l == r) {//待排数组只有一个数时
return;
}
int mid = l + ((r - l) >> 1);//数组索引中间值//int mid = (l + r) / 2的形式不安全
sortProcess(arr, l, mid);//排mid左边的值
sortProcess(arr, mid + 1, r);//排mid右边的值
merge(arr, l, mid, r);//左右两边都排好之后进行左右两边排序
}
/**
* 合并
* @param arr 原数组
* @param l 原数组左边部分起始值
* @param mid 原数组中间索引号
* @param r 原数组右边部分结束值
*/
private 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) {//mid左边部分和右边部分均没有越界
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];
}
}
例子1:
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组 的小和。
例子:
[1,3,4,2,5] 1左边比1小的数,没有;
3左边比3小的数,1;
4左边比4小的数,1、3;
2左边比2小的数,1;
5左边比5小的数,1、3、4、2;
所以小和为1+1+3+1+1+3+4+2=16
/**
* 归并排序
* @param arr 待排的数组
* @return 小和
*/
private static int mergeSort(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
return sortProcess(arr, 0, arr.length - 1);
}
/**
* 排序过程
* @param arr 待排子数组
* @param l 子数组开始位置
* @param r 子数组结束位置
* @return 子项小和
*/
private static int sortProcess(int[] arr, int l, int r) {
if (l == r) {
return 0;
}
int mid = l + ((r - l) / 2);
return sortProcess(arr, l, mid)
+ sortProcess(arr, mid + 1, r)
+ merge(arr, l, mid, r);
}
/**
* 合并
* @param arr 原数组
* @param l 原数组左边部分起始值
* @param mid 原数组中间索引号
* @param r 原数组右边部分结束值
* @return 子项小和
*/
private 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 result = 0;
while (p1 <= mid && p2 <= r) {
result += 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 result;
}