一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
背景引入:我有个朋友,自认为掌握了快速排序,可每次写的时候都会有一点小瑕疵。我看的出来,他很困扰啊。我作为他的好兄弟、正义的伙伴自然是见不得朋友烦恼的。这一次我要让他再也不会写错快速排序。
算法思想:
- 快排的核心是确认一个基准点(通常是数组的第一个)。
- 将数组中小于基准点的数放到基准点(下文用flag表示)的左边。大于flag的数放到右边。
- 这时候我们有了两个新的数组,即 小于基准点的数组 和 大于基准点的数组
- 对这两个数组重复前两步的操作,如此递归下去,直到数组长度 <= 1
- (我兄弟很聪明哇,我一说他就懂了。我好有面子嘻嘻)
给朋友展示了一下代码
show code
//解法1
let quick_sort = function (nums, start, end){
if(start >= end) return //递归结束的条件
let left = start, right = end
let flag = nums[start] //确认基准点
while(left < right){
while(nums[right] >= flag && left < right){ //数组从后往前查找小于flag的位置
right --
}
while(nums[left] <= flag && left < right){ //数组从前往后查找大于flag的位置
left ++
}
if(left < right){ //一定需要对left和right的大小进行判断
[nums[left], nums[right]] = [nums[right], nums[left]] //交换位置
}
}
nums[start] = nums[left] //将第一个点的值和循环结束的位置的值进行交换
nums[left] = flag //循环结束的位置放入flag
quick_sort(nums, left + 1, end)
quick_sort(nums, start , left - 1)
}
如果只是单单展示了算法,我并不觉得我那位朋友可以掌握下来
于是我给朋友总结了几点:
- 注意递归结束的条件
- 时刻注意left < right, 重要的事情要注意三次
- 退出循环时即(left == start时) left的值放到start的位置上,flag的值放到left。
此时flag左边的值就都是小于它的,右边都是大于它的
复杂度:提一嘴,快排的平均时间复杂度O(nlogn)
快排不难理解,但是刚开始写可能会比较难写。朋友回去练了几遍后跟我说:“快排也不过如此”
感谢观看到这里。如果这篇文章让你觉得快排不过如此的话,点个小小的赞吧。
兄弟每次都给我点赞,我很有面子