分解
:将n个元素分成各含n/2个元素的子序列解决
:对两个子序列递归地排序合并
:合并两个已排序的子序列以得到排序结果/**
* 归并排序
*
* @author LRRacac
*
*/
public class MergerSort {
// 定义一个辅助数组
public static int[] helper;
/**
* 归并排序方法
*/
public static void sort(int[] arr) {
helper = new int[arr.length]; // 为辅助数组设置长度
mergeSort(arr, 0, arr.length - 1); // 进行归并排序
}
/**
* 排序方法
*
* @param arr---待排序数组
* @param l---左边界
* @param r---右边界
*/
public static void mergeSort(int[] arr, int l, int r) {
if (l >= r)
return;
int mid = (l + r) >> 1; // 获取中间位置
mergeSort(arr, l, mid); // 对mid左侧(含mid)进行归并排序
mergeSort(arr, mid + 1, r);// 对mid右侧进行归并排序
merge(arr, l, mid, r); // 最后将分别排序完毕的左右侧进行合并,从而完成对整个数组的排序
}
/**
* 合并方法---将已经分别有序的左右两部分数组进行整体合并
*
* @param arr---待排序的数组
* @param l---左边界
* @param mid---分界线(mid左右侧分别有序)
* @param r---右边界
*/
public static void merge(int[] arr, int l, int mid, int r) {
System.arraycopy(arr, l, helper, l, r - l + 1); // 复制原数组元素到辅助数组
int pleft = l; // 左指针
int pright = mid + 1; // 右指针
int current = l; // 用于记录原数组中待填入元素的索引
while (pleft <= mid && pright <= r) { // 当左右指针有一个已经扫完了,就退出循环
if (helper[pleft] <= helper[pright]) { // 当左指针所指元素小于等于右指针所指元素时
arr[current] = helper[pleft];
current++;
pleft++;
} else { // 当左指针所指元素大于右指针所指元素时
arr[current] = helper[pright];
current++;
pright++;
}
}
// 至此,左右两指针其一已经扫描完毕,如果是左侧先扫描完则无需处理
// 如果是右侧先扫描完,则需将左侧为扫描完的元素都放入数组末尾
while (pleft <= mid) {
arr[current] = helper[pleft];
current++;
pleft++;
}
}
}
测试代码:
import java.util.Arrays;
/**
* 归并排序测试代码
* @author LRRacac
*
*/
public class MergeSortTest {
public static void main(String[] args) {
int[] arr = {12, 2, 20, 2, 11, 7, 10, 5, 6, 13};
System.out.println("归并排序前:"+Arrays.toString(arr));
MergerSort.sort(arr); //调用归并排序方法
System.out.println("归并排序后:"+Arrays.toString(arr));
}
}
结果展示:
/**
* 求数组中逆序对个数
* @author LRRacac
*
*/
import java.util.Arrays;
public class InversePair {
// 定义一个辅助数组
public static int[] helper;
// 定义一个count变量用于记录逆序对个数
public static int count = 0;
public static void main(String[] args) {
int[] arr = {2, 8, 5, 4, 6};
System.out.println("数组:"+Arrays.toString(arr)); //打印原数组
System.out.println("逆序对的个数为:"+getCount(arr)+"个"); //调用getCount方法获取逆序对个数
}
/**
* 获取逆序对个数
*/
public static int getCount(int[] arr) {
helper = new int[arr.length]; // 为辅助数组设置长度
mergeSort(arr, 0, arr.length - 1); // 进行归并排序
return count; //返回逆序对个数
}
/**
* 排序方法
*
* @param arr---待排序数组
* @param l---左边界
* @param r---右边界
*/
public static void mergeSort(int[] arr, int l, int r) {
if (l >= r)
return;
int mid = (l + r) >> 1; // 获取中间位置
mergeSort(arr, l, mid); // 对mid左侧(含mid)进行归并排序
mergeSort(arr, mid + 1, r);// 对mid右侧进行归并排序
merge(arr, l, mid, r); // 最后将分别排序完毕的左右侧进行合并,从而完成对整个数组的排序
}
/**
* 合并方法---将已经分别有序的左右两部分数组进行整体合并
* 利用归并排序的合并思路来统计逆序对个数
*
* @param arr---待排序的数组
* @param l---左边界
* @param mid---分界线(mid左右侧分别有序)
* @param r---右边界
*/
public static void merge(int[] arr, int l, int mid, int r) {
System.arraycopy(arr, l, helper, l, r - l + 1); // 复制原数组元素到辅助数组
int pleft = l; // 左指针
int pright = mid + 1; // 右指针
int current = l; // 用于记录原数组中待填入元素的索引
while (pleft <= mid && pright <= r) { // 当左右指针有一个已经扫完了,就退出循环
if (helper[pleft] <= helper[pright]) { // 当左指针所指元素小于等于右指针所指元素时
arr[current] = helper[pleft];
current++;
pleft++;
} else { // 当左指针所指元素大于右指针所指元素时
arr[current] = helper[pright];
current++;
pright++;
count += mid - pleft + 1; // 当右侧元素大于左侧时,则为逆序,此时与该元素组成逆序对的个数为左侧剩余元素的个数
}
}
// 至此,左右两指针其一已经扫描完毕,如果是左侧先扫描完则无需处理
// 如果是右侧先扫描完,则需将左侧为扫描完的元素都放入数组末尾
while (pleft <= mid) {
arr[current] = helper[pleft];
current++;
pleft++;
}
}
}
测试结果:
骚话时刻:
感觉每个人多多少少都有点完美主义吧,总觉得一件事如果有了污点就不愿意再做下去,期待着下一个节点,为自己蹲好理由再重新出发,可在一件事情完成之前难免都会有点磕磕绊绊,这可咋办?
拿我自己学习算法做个比方吧,比如我前一段时间学排序学到一半,突然被各种各样的事情打断,以至于有几天没有接触它,自己的计划表上算法学习的任务也越欠越多,不知道你们怎么想,反正我是真的会因此抵触去学习算法。于是就越拖越久…我身边也有很多这样的例子,比如很多人打卡背单词,坚持了一阵子,结果有一天突然断了,可能下一次开始就是数n天之后hhh(偷笑,自己也中招过)。
我认为这是完美主义(处女座?)的一种体现吧(不排除有些人就是懒),总觉得一旦没有达到预期的样子,整个事情就不再完美,也就不想做下去。可能会有人说那就乐观一些,不要管他,学就是了。叫人乐观恐怕是最敷衍的方式了吧,毕竟谁都想乐观一点,问题是怎么乐观呢?我的心情就是这样,怎么调整呢?
好吧,其实我也不知道怎么处理(如果有人坚持看我废话到这里,恐怕想要锤si我)
哈哈哈,但是,就我经历来说,我会推荐你,别想!不完美就不完美!不完美我也要学!
毕竟人都是爱幻想的,完美的事情几乎是不存在的,那就接受不完美嘛,这样才有成长的空间呀,人生不就是让自己越来越成熟,没经历过啥风风雨雨,以后老了回忆起来都没啥意思对吧
归并排序告诉我,不能一次性完整地完成某项任务,那就一刀切,切成一小块一小块去完成,最后整合起来就非常强大了。所以不能完美地完成任务,那就不完美地做吧,点点滴滴积累起来你也会变得强大