最近看了一道关于“阿里两万多员工如何按年龄排序”的面试题,很想记录一下解决问题的思路。如下:考虑到大基数和稳定性,我们采用mergeandsort的算法;合并算法分为两个灵魂步骤,即:分裂=>合并;我们先把20000多员工的基数缩减为6个员工的基数,年龄数组为[25,18,17,31,25,30],实现第一个灵魂操作,拆分:拆分思路merge算法是将一个数组一分为二,然后继续将划分后的数组一分为二,直到单个数组的长度为1,不能再进一步划分;如上图所示,一个长度为6的数组按照左右结构拆分为6个长度为1的数组,拆分完成。这时候我们从下往上回溯,合并数组,示意图:6个长度为1的数组合并后变成一个长度为6的数组,只是排序变了。这就是合并算法。下面是代码实现:一步步来,第一步先实现拆分://拆分函数mergeSort(arr){console.log(`arr=${arr}`)if(arr.length==1){//如果数组长度为1,返回Arrayreturnarr}varmid=Math.floor(arr.length/2);//将数组一分为二varleft=arr.slice(0,mid);varright=arr.slice(mid);mergeSort(left);//如果数组长度不为1,继续递归拆分,(从console可以看到递归会先执行left,再执行right)mergeSort(right)}console.log(mergeSort([25,18,17,31,25,30]))控制台打印出结果:此时我们可以看到我们已经递归地将数组拆分为6个长度为1的数组,然后进行第二步合并,合并的思路首先是左右数组比较元素的大小,然后提取大数(或小数)存入第三方数组,直接添加代码://Mergefunctionmerge(left,right){vararr=newArray;//新建一个三角数组if(left[0]<=right[0]){//比较左首位和右首位,取小者,取出小者推入第三方数组arr.push(left.shift())}else{arr.push(right.shift())}returnarr.concat(left).concat(right)//合并提取的数组和原数组成一个阵列};console.log(merge([25],[30]))//到这里为止的代码只是展示了合并的原理和思路,还不完整,我们不着急,先用一个简单的单元素数组进行排序合并,也是第一层合并合并控制台打印出[25,30],说明我们的合并排序都成功了。接下来,我们将对这两个函数进行升级,使其可以正式操作复杂的归并排序://Mergefunctionmerge(left,right){vararr=newArray;//创建一个新的第三方数组while(left.length>0&&right.length>0){////比较左首位和右首位,取小的取小的出来,推入第三方数组if(left[0]<=right[0]){arr.push(left.shift())}else{arr.push(right.shift())}};returnarr.concat(left).concat(right)//将提取的数组和原数组合并为一个数组};//SplitfunctionmergeSort(arr){console.log(`arr=${arr}`)if(arr.length==1){//如果数组长度为1,返回数组returnarr};varmid=Math.floor(arr.length/2);//将数组一分为二varleft=arr.slice(0,mid);varright=arr.slice(mid);返回合并(mergeSort(左),mergeSort(右))};安慰。log(mergeSort([25,18,17,31,25,30]))控制台打印:至此,我们的归并排序成功了!欢迎大家不分大小,指正讨论
