首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

面试高频题:归并排序详解

比如归并排序,“归并”二字就是“递归”加“合并”。 ——它是典型分而治之算法。 上图中,先把数组一分为二,然后递归排序好每部分,最后合并。...我们再回忆一下归并算法步骤: 1、数组分成两半,left和right 2、递归处理left 3、递归处理right 4、合并二者结果 然后再来轻松翻译成代码: function mergeSort...mergeSort(array.slice(m)) return merge(left, right)} 递归是自身调用自身,不能无限次地调用下去,因此需要有递归出口(初始条件)。...它递归出口是,当数组元素个数为小于2时,就是已经是排好序,不需要再递归调用了。...归并排序需要额外空间,空间复杂度为O(n),不是本地排序,相等元素是不会交换前后顺序,因而是稳定排序。时间复杂度为O(nlogn),是比较优秀算法,面试题中出现概率也很高。

34700

数据结构从入门到精通——归并排序

归并排序是一种典型分治算法,它通过递归地将问题分解为更小问题来解决。这种递归性使得归并排序实现相对简单明了,也易于理解和维护。...然而,递归也可能导致栈空间消耗,因此处理大规模数据时需要注意递归深度问题。 综上所述,归并排序作为一种高效稳定排序算法,实际应用中具有广泛应用场景。...归并排序是一种分治算法,首先将原始数组递归地分成两个子数组,然后对子数组进行排序,最后将排序子数组合并成一个有序数组。 代码中MergeSort函数是对外接口,用于调用归并排序算法。...首先申请了一个临时数组tmp,用于存放归并过程中临时结果。然后调用_MergeSort函数进行实际归并排序操作。 _MergeSort函数是核心函数,用于实现归并排序递归过程。...归并排序是一种分治算法,通过将数组分成两个部分,分别对这两个部分进行排序,然后将排好序两个部分合并起来。 代码中,首先创建一个临时数组tmp,用来合并过程中暂存排序结果。

11810
您找到你想要的搜索结果了吗?
是的
没有找到

排序算法】 归并排序详解!深入理解!思想+源码实现!

☁️分治法 ​ 分治法归并排序应用是将问题分解成更小问题,然后分别解决这些子问题,最后将子问题合并起来得到原问题解。...⭐代码实现详解: 首先,将整个序列分为两部分,分别递归调用_MergeSort函数对左右两部分进行排序。...然后,计算中间位置mid,并分别递归调用_MergeSort函数对左右两部分进行排序。 接下来,进行归并操作。...☁️非递归版归并实现 ​ 非递归版是递归上进行了修改,将其递归改为了循环。...递归实现归并排序代码简洁易懂,但是由于递归调用开销比较大,所以实际应用中可能会使用迭代方式来实现归并排序。 适用性:归并排序适用于各种数据规模排序,而且对于大规模数据排序效果较好。

26210

重读算法导论之算法基础

只不过归纳法中,归纳步是无限地使用,而这里存在循环终止,停止归纳。 ---- 用循环不变式验证插入排序 初始化: 从上面的代码可以看到。...循环之前,我们假设排好序部分A只包含一个元素,此时A当然是满足排好序。即初始化A满足循环不变式 保持:下面分析每一个循环过程。...直接来看下分治算法求解三个步骤: 分解:分解原问题为若干子问题,这些子问题就是原问题规模较小实例 解决:递归地求解各个子问题 合并合并问题解成原问题解 ​ 算法上分治一种最常见表现就是递归调用...递归调用就是一个方法不停地对自己进行调用,每次调用问题规模都会缩小,直至达到方法返回临界值。归并排序就是分治算法思想一个典型应用。...因此,归并排序中当子问题变得足够小时,采用插入排序来使递归叶变粗是有意义

891100

文心一言 VS 讯飞星火 VS chatgpt (203)-- 算法导论15.3 2题

这是一个典型分治算法,它首先将数组一分为二,然后递归地对每一半进行排序,最后将两个已排序部分合并成一个有序数组。...然而,归并排序这种分治算法中,备忘技术并不有效,因为归并排序递归过程中,子问题并不是独立。...归并排序中,我们需要同时合并两个已排序子数组,而这个合并过程是无法通过仅仅存储子数组前缀来避免重复计算。...归并排序是一种分治算法,它核心思想是将数组分成两半,分别对这两部分进行排序,然后将排序部分合并。这个过程会递归地继续下去直到每个子数组只有一个元素,此时它们已经是排序。...即使子数组不同递归路径上出现,它们也是独立排序合并操作是唯一,因此没有必要缓存之前合并结果。 3.

12620

排序7:归并排序

目录 1.排序思想 2.图解 3.递归版本 3.1子排序代码实现 3.2 剩下主体部分 4.非递归版本 5.特性总结 ---- 1.排序思想 归并排序(MERGE-SORT)是建立归并操作上一种有效排序算法...分到最细时候每次排序是两个数字排序或者是一个数字原地不动,那么我们可以设置一个for循环,每次 i 加上两个gap值,就做到了跳到下一个需要排序区间。...然后每次gap值×2,就解决了两个区间合并问题。 接下来就是细节问题:我们从前面可以知道我们下标是两个gap移动,那么如果剩下数个数不满足加值呢?此时就会发生越界问题了。...修正第一组尾部: 修正第二组全部: 修正第二组尾部: 考虑完了越界问题,才能够高枕无忧排序,非递归排序递归思路一样。这里就不过多叙述。...归并缺点在于需要 O(N) 空间复杂度,归并排序思考更多是解决磁盘中排序问题。 2. 时间复杂度: O(N*logN) 3.

27830

【算法】归并排序

归并排序 先分割为两部分 , 然后两边分别排序 , 再进行合并 ; 先局部有序 , 后整体有序 ; 归并排序 与 快速排序 比较 , 其比 快排 多花费 O(n) 空间 , 其合并两个数组时..., 不能在原数组中进行 ; 快速排序 , 始终都在原数组中进行 , 只涉及到交换数组中元素 ; 正式由于该额外数组存在 , 因此归并排序 , 并不是排序最优算法 ; 算法要点 : 合并数组中 ,...创建数组时机 , 不要放在递归中 , 递归调用很多次 , 频繁创建销毁数组 , 很耗费时间和空间 ; 代码示例 : class Solution { /** * 归并排序...int mergeArray[] = new int[A.length]; // 递归调用排序算法 mergeSort(A, 0, A.length...// 左侧排序 mergeSort(array, start, (start + end) / 2, mergeArray); // 右侧排序 mergeSort

69710

数组归并排序

(声明:文章全部图片均来自 传智播客 教师课件)归并排序是一种空间换时间做法,排序速度当然会提高很多,归并排序中会产生一个临时数组,这个临时数组用来把不断拆分到最后有序数据进行合并,最后再把合并数据重新赋值给原数组...主要分为以下三个步骤: 1、把原数组无限拆分到最少元素(直至剩余一个)如下图表示: 2、把拆分两组数据合并到临时数组,如下图表示: 图片 3、最后把临时数组中值覆盖掉原始数组值,整个过程就是下图这样...// 如果i下标还没到最最后位置,那么就循环把值赋给临时数组 temp[length] = arr[i]; length++; i++; } while (j <= mid) { // 如果j下标还没到最最后位置...) { if (first < last) { // 将数据分割成两份 int mid = (first + last) / 2; // 一次递归把两份左侧数据和右侧数据再次拆分 mergeSort...(arr, first, mid, temp); mergeSort(arr, mid + 1, last, temp); // 把拆分数据进行排序递归中,是从拆分到最后2个或3个数进行排序) mergeArray

9910

你所能用到数据结构(四)

递归这个词我理解应该是传递和回归,如何把自身状态传递下去和如何回归到一个结果上是递归问题基本思维方式。...关于如何归,就是要找到递归中止条件,比如斐波那契数列那个,n=0就是数列中止条件,别小看这个中止条件,如果不能找出这个中止条件或者定义错误的话,后果就是无限递归,导致程序堆栈崩溃,最终整个程序就很快崩溃掉了...那么,再来看一个二分搜索好了,二分搜索是已经排序数列里面寻找目标数,比如{1,2,...,10},这种,如果是寻找2,那么先求出这一组数中值5,2比5小,从而转到0-5这个部分,其中值是2,然后就找到了...归并排序简单将就是将一个数列不断平均分为两个小数列,然后每个小数列独立排序之后再合并在一起排序,也就是用若干有序子序列得到一个有序数列,为了说明,还是用一个例子好了,就用百度这个例子好了: 如...,然后排序右边,最后将两个子序列合并起来,是不是思路特别的清晰?

612100

Java实现-归并排序算法-动图详解

归并排序详解(后序遍历) 大家可能都对二叉树后序遍历比较熟悉,实际上归并排序本质框架就是二叉树后序遍历,根结点遍历只不过换成了治(Merge方法调用),本文将结合动图+代码方式进行最通俗讲解...「基本思想」:利用归并思想实现排序方法,该算法采用经典分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小问题然后递归求解,而治(conquer)阶段则将分阶段得到各答案修补在一起...left==right,每组right和left都不相同,左边递归调用传值left值不变,right值为mid,右边递归调用传值left为mid+1,因为mid是左边最后一个,所以要加1,右边值就是...mergeSort(arr, left, mid, temp); //向右递归进行分解 动图分组中靠右部分 mergeSort(arr, mid +...时间复杂度:O(nlogn) 空间复杂度:O(n+logn) 由于归并排序归并过程中需要与原始记录序列同样数量存储空间存放归并结果以及递归深度为log2n栈空间,因此空间复杂度为O(n+logn)

79110

归并排序含非递归

1.归并排序原理 归并排序是建立归并操作上一种有效排序算法,该算法是采用分治法一个非常典型应用。...如图所示: 2.实现归并排序 归并排序需要开额外空间来辅助实现 之所以不在原数组实现,是因为如果你使用交换方式来进行排序,可能会将原数组已经排好序部分又一次变回无序,而使用令数组向后移动方式进行对应排序...归并排序需要开额外空间,但每次递归都要开空间显然是不合理,因此我们使用一个函数来完成递归部分。...注意:两个区间不知道是哪个区间先完成循环,因此在外面需要将未完成循环区间,补充回辅助数组中。 搞定完归并后,使用memcpy将辅助数组中内容拷贝回原数组,排序便结束了。...注意:我们之前使用拷贝函数均是拷贝2*gap个过去,在这里显然不合适,总区间长度应修正 为end2-begin1,这个修正不应该放在最后,因为进行归并期间,begin1会++至end1 也不应该放在判断

11910

一文带你读懂排序算法(四):归并算法

归并排序基本思想核心是分治,就是把一个复杂问题分成两个或多个相同或相似的子问题,然后把子问题分成更小问题,直到子问题可以简单直接求解,最原问题解就是子问题合并。...算法思想 归并排序主要思想是分治法,排序方法就是按照大小顺序合并两个元素,接着依次按照递归返回顺序,不断地合并排好序子数组,直到最后把整个数组顺序排好。...主要过程是: 将n个元素从中间切开,分成两部分。(左边可能比右边多1个数) 将步骤1分成部分,再分别进行递归分解。...每一层里,我们都要进行合并,所涉及到元素其实就是数组里所有元素,因此,每一层合并复杂度都是 O(n),所以整体复杂度就是 O(nlogn)。...建议:归并算法思想很重要,其中对两个有序数组合并操作,很多面试题里都有用到,建议大家一定要把这个算法练熟。 —END—

29220

手把手教你写归并排序算法 (Java代码)

即先使每个子序列有序,再将已有序子序列合并,得到完全有序序列。这里给出一种递归形式归并排序实现。...mergeSort(arr,left,mid);//对左半部分调用递归方法,使其有序 mergeSort(arr,mid + 1,right);//对右半部分调用递归方法...(arr,0,arr.length - 1);//调用写好递归版归并排序方法 } 至此,我们便完成了归并排序算法代码实现。...归并排序算法排序时首先将问题进行分解,然后解决子问题,再合并,所以总时间=分解时间+解决子问题时间+合并时间。...分解时间就是把一个数组分解为左右两部分,时间为一常数,即O(1);解决子问题时间是两个递归方法,把一个规模为n问题分成两个规模分别为n/2问题,时间为2T(n/2);合并时间复杂度为O(n)。

55630

排序进行曲-v3.0

空间复杂度分析: 每次递归合并过程中,需要创建临时数组来存储合并子数组,临时数组空间复杂度为 O(n)。 每次递归合并完成后,临时数组会被销毁,所以整个归并排序空间复杂度为 O(n)。...例如,某个数据库表中有大量数据需要按照 某个字段进行排序,可以使用归并排序算法将数据分割成多个较小部分,分别对这些部分进行排序,然 后再将排序部分合并起来。...Other 这些例子只是归并排序实际中一些应用,实际上归并排序思想和方法也可以应用于其他问题,只需要将 问题分割成更小问题,并将子问题结果合并起来。...解释 mergeSort方法中,首先判断数组长度是否小于等于1,如果是,则直接返回。然后创建一个临时数组 temp,并调用mergeSort方法对数组进行递归排序。...mergeSort方法中,首先计算出数组中间位置 mid,然后分别对左半部分和右半部分进行递归排序,最后调用merge方法将排序左右两部分合并起 来。

11720

第十三天、归并排序

r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余元素复制到r中从下标k到下标t单元。...归并排序算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序区间[s,t]。     ...,iMidIndex); /*递归调用将iSourceArr[iMidIndex+1]~iSourceArr[iEndIndex]归并成有序*/ MergeSort(iSourceArr...,iTempArr,iMidIndex+1,iEndIndex); /*调用函数将前两部分归并到iSourceArr[iStartIndex]~iSourceArr[iEndIndex]...,j = iMidIndex + 1,k = iStartIndex; while((i <= iMidIndex) && (j <= iEndIndex)) //当i和j都在要合并部分中成立

48500

Go 数据结构和算法篇(七):归并排序

所谓归并排序,指的是如果要排序一个数据序列,我们可以先把该序列从中间分成前后两部分,然后对这两部分分别做排序操作,再将排好序部分合并在一起,这样整个数据序列就都有序了。...归并排序使用了分治思想,分治,顾名思义,就是分而治之,将一个大问题分解成小问题来解决。说到这里,可能你会联想起我们之前讲到一个编程技巧 —— 递归,没错,归并排序就是通过递归来实现。...二、示例代码 通过上面的分析,我们知道归并=递归+合并,对应 Go 实现代码如下: package main import ( "fmt" ) // 归并排序 func mergeSort...归并排序时间复杂度推导过程 归并思路是将一个复杂问题 a 递归拆解为子问题 b 和 c,再将子问题计算结果合并,最终得到问题答案,这里我们将归并排序时间复杂度设为 T(n),则 T(n) =...2*T(n/2) + n,其中 T(n/2) 是递归拆解第一步对应子问题时间复杂度,n 则是排序合并函数时间复杂度(一个循环遍历),依次类推,我们可以推导 T(n) 计算逻辑如下: T(n)

24520

数据结构排序——详细讲解归并排序(c语言实现递归及非递归

,然后将排序子序列合并起来。...合并子序列过程中,需要比较两个子序列元素,并按顺序将它们合并成一个有序序列 注意:归并排序关键在于合并两个有序子序列,这一步需要额外空间来存储中间结果。...实际实现中,可以使用递归或非递归方式来完成归并排序 2.递归实现 递归归并排序: 如果序列长度小于等于1,无需排序,直接返回 将序列分成两个子序列,分别进行递归归并排序 合并两个已排序子序列...(a, tmp, left, mid); _MergeSort(a, tmp, mid+1,right );//这两部分都有序啦 //开始归并:归并到到tmp数组相同位置,再拷贝回去 int...,它避免了递归调用带来额外开销,通常使用循环和迭代来实现归并排序过程: 确定归并区间思路:对于给定数组,首先将相邻元素两两归并(gap=1),然后将归并区间长度不断扩大,依次归并相邻区间

10510

合并排序

分治算法: 用分治策略实现n个元素进行排序方法。 基本思想: 将待排序元素分成大小大致相同两个子集合,分别对两个子集合进行排序,最终排好序子集合合并成所要求排好序集合。...源码: /* * mergeSort.cpp * 合并排序算法,算法导论P.17 * Created on: 2011-12-21 * Author: LiChanghai */...subMerge对任意数组排序,p, r为下标 //mergeSort(A, p, r)首先将数组A分为两部分 //然后递归调用其本身对这两部分 分别排序 //依次递归下去,直到只剩2个数时候完成这两个数排序...//然后再层层返回调用处,将已排好序子序列合并成更大有序序列 //最后一次调用subMerge时完成数组排序 template void mergeSort(vector...(vec, iterHead, iterDivide+1); //递归调用自身对前半段排序 mergeSort(vec, iterDivide+1, iterTail); //递归调用自身对后半段排序

72090
领券