1 解题思路
归并排序是使用分治策略(分治法是将大问题分成小问题,对小问题来求解,然后将分解的答案合并成大问题需要的答案)实现的排序算法,归并排序的核心思想是把数组 nums 一分为二,把分好的两个子数组分别进行排序,然后再合并两个排好的子数组得到合并后的有序数组,依次类推,直到把数组拆分的只剩一个元素,然后再依次合并。归并排序使用递归的思想,先依次拆分数组,然后再依次合并,跟快速排序某些程度上是相反的,快速排序是找目标值的位置然后拆分数组。
示例:
输入 nums = {9,4,5,2,1,7,4,6} 输出 nums = {1,2,4,4,5,6,7,9}
求解的过程如下图所示:
可以看到这种结构很像一个完全二叉树,树的深度是 logN,本文采用递归来实现归并,所以递归的深度为 logN。
如何合并两个有序数组?合并两个有序数组需要借助第三个数组来存储合并后的数组,假设数组 nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},两个有序数组从左往后一次比较值的大小,把值小的放入第三个数组nums3中。这些需要数组下标,假设数组 nums1 下标从 0 开始 index1 = 0,数组 nums2 下标从 0 开始,index2 = 0。 执行步骤:
第1步:index1 = 0,index2 = 0,比较 4 和 1 ,1 小于 4 ,所以把 1 放入数组 nums3 中,此时数组情况:
nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},nums3={1}
然后 index2++ = 1。
第2步:index1 = 0,index2 = 1,
nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},nums3={1,2}
此时 index2++ = 2。
第3步:index1 = 0,index2 = 2,
nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},nums3={1,2,3}
此时 index2++ = 3
第4步: index1 = 0,index2 = 3,
nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},nums3={1,2,3,4}
此时 index1++ = 1
第5步: index1 = 1,index2 = 3,
nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},nums3={1,2,3,4,5}
此时 index1++ = 2
第6步:index1 = 1,index2 = 3,
nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},nums3={1,2,3,4,5,6}
此时nums2已经遍历完成。
第7步:依次将 nums1 中剩下的元素插入 nums3 中
nums3={1,2,3,4,5,6,7,8}
第8步:把nums3中的元素按顺序放入nums中,最终得到有序数组
nums = {1,2,3,4,5,6,7,8}
2 编码实现
int[] tmps = new int[nums.length];
public static void mergeSort(int[] nums,int left,int right){
if(left<right){
int mid = (left+right)/2;
mergeSort(nums,left,mid);
mergeSort(nums,mid+1,right);
sort(nums,left,mid,right);
}
}
public static void sort(int[] nums,int left,int mid,int right){
int leftIndex = left;
int rightIndex = mid+1;
int tmpIndex = left;
while(leftIndex<=mid && rightIndex<=right){
if(nums[leftIndex] <= nums[rightIndex]){
tmps[tmpIndex++] = nums[leftIndex++];
} else {
tmps[tmpIndex++] = nums[rightIndex++];
}
}
while(leftIndex<=mid){
tmps[tmpIndex++] = nums[leftIndex++];
}
while(rightIndex<=right){
tmps[tmpIndex++] = nums[rightIndex++];
}
for(int i=left;i<=right;i++){
nums[i] = tmps[i];
}
}
3 时间复杂度和空间复杂度
由归并排序的树形结构可以看到树的深度是 logN ,每一层最多需要N次比较,所以归并排序的时间复杂度 T(n)=O(NlogN)。归并排序的时候需要使用到额外的数组tmps,所以空间复杂度 S(n) = O(n)
本文详细介绍了归并排序的基本原理,通过递归拆分和合并有序子数组的方法,展示了其过程。同时,讨论了算法的时间复杂度为O(NlogN),空间复杂度为O(n)。
316

被折叠的 条评论
为什么被折叠?



