系列文章目录
提示: 以下是其他排序算法的链接🔗
文章目录
- 系列文章目录
- 什么是归并排序?
什么是归并排序?
归并排序(Merge Sort)是一种基于分治思想的排序算法,它将待排序序列分成两个子序列,分别对子序列进行排序,然后将两个有序的子序列合并成一个有序的序列。
归并排序的步骤如下:
- 将待排序序列分成两个子序列,直到每个子序列只有一个元素。
- 对每个子序列进行排序,可以使用递归调用归并排序。
- 将两个有序的子序列合并成一个有序的序列,得到最终的排序结果。
归并排序的时间复杂度为O(nlogn),其中n是待排序序列的长度。归并排序是一种稳定的排序算法,它的空间复杂度为O(n),需要额外的空间来存储临时的子序列。
代码模板(示例):
递归版
class Solution {
// 全局变量节省空间
public static int[] tmp = null;
public int[] sortArray(int[] nums) {
//归并排序(递归)
tmp = new int[nums.length];
mergeSort(nums, 0, nums.length - 1);
return nums;
}
public void mergeSort(int[] nums, int left, int right) {
if (left >= right)//退出条件
return;
//分成两半
int mid = left + (right - left) / 2;
//左右分开排序
mergeSort(nums, left, mid);
mergeSort(nums, mid + 1, right);
//合并左右
int cur1 = left, cur2 = mid + 1, i = 0;
while (cur1 <= mid && cur2 <= right)
tmp[i++] = nums[cur1] > nums[cur2] ? nums[cur2++] : nums[cur1++];
//处理未拷贝的数
while (cur1 <= mid)
tmp[i++] = nums[cur1++];
while (cur2 <= right)
tmp[i++] = nums[cur2++];
//将排序完成的数拷贝回原数组
System.arraycopy(tmp, 0, nums, left, right - left + 1);
}
}
非递归版
class Solution {
// 全局变量节省空间
int[] temp = null;
public int[] sortArray(int[] nums) {
// 归并排序(非递归)
temp = new int[nums.length];
// Nor 表示非递归
mergeSortNor(nums);
return nums;
}
private void merge(int[] arr, int left, int right, int mid) {
int s1 = left, s2 = mid + 1;
// int[] temp = new int[right - left + 1];//开辟临时数组
int k = 0;//temp的初始下标
while (s1 <= mid && s2 <= right)// 将较小的数依次插入 temp
if (arr[s1] <= arr[s2])
temp[k++] = arr[s1++];
else
temp[k++] = arr[s2++];
// 防止有数未插入
while (s1 <= mid)
temp[k++] = arr[s1++];
while (s2 <= right)
temp[k++] = arr[s2++];
System.arraycopy(temp, 0, arr, left, right - left + 1);
}
public void mergeSortNor(int[] arr) {
int len = arr.length;
int gap = 1;//步长用来划分合并数组
while (gap < len) {
for (int i = 0; i < len; i += 2 * gap) {
int left = i, mid = left + gap - 1, right = mid + gap;
// 解决步长过大的问题(即步长大+一部分数组大于整体数组长度)
if (mid >= len)
mid = len - 1;
if (right >= len)
right = len - 1;
merge(arr, left, right, mid);
}
gap *= 2;// 步长不断扩大
}
}
}