携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情
前言
十大基础算法中,有三个算法可能经常会在面试中遇到:归并排序、快速排序、拓扑排序。它们的核心思想都是分而治。将复杂问题简单化去解决。
合并排序(归并排序)
基本思路
核心就是分而治之,将一个复杂问题拆解成两个或多个相似的子问题,然后再继续拆解成更小的子问题,直接拆解成可以简单求解的问题进行解决,最后再合并。
归并排序,先划分成2个子数组,再对每个子数组划分成更小的数组,直到子数组只有一个元素再开始排序
[3, 44, 38, 5, 47, 15, 2, 26, 27]
[3, 44, 38, 5 ,47 ] [15, 2, 26, 27]
[3,44,38] [5,47] [15,2] [26, 27]
[3,44] [38] [5] [47] [15] [2] [26][27]
[3] [44]
merge
[3, 44] [38] [5] [47]. [15] [2][26][27]
[3,38,44] [5,47] [2,15] [26,27]
。。。
代码示例
func sort(arr []int, left int, right int) {
if left >= right { // 只剩下最后一个元素则直接返回
return
}
mid := left + (right-left)/2
sort(arr, left, mid)
sort(arr, mid+1, right)
// 排好序后进行组合
merge(arr, left, mid, right)
}
func merge(arr []int, left int, mid int, right int) {
tempArr := arr
k := left
i := left
j := mid + 1
for {
if i > mid {
k += 1
j += 1
arr[k] = tempArr[j]
} else if j > right {
k += 1
i += 1
arr[k] = tempArr[i]
} else if tempArr[j] < tempArr[i] {
k += 1
j += 1
arr[k] = tempArr[j]
} else {
k += 1
i += 1
arr[k] = tempArr[i]
}
if k <= right {
break
}
}
}
快速排序
基本思路
快速排序也是采用分治的思想。大致可以分成三个步骤:
- 选择一个元素作为“基准“ pivot
- 所有小于“基准”元素,都转移到基准的左边,大于的都转移到右边。
- 对“基准”左右两边的两个子集,继续重复第一步和第二步,直到所有的子集只剩下一个元素为止。
[3, 44, 38, 5, 47, 15, 2, 26, 27]
第一轮,选择3为基准,遍历到 2 小于基准,那么需要将 2 转移到基准之前。
将 2 和 3 的位置置换:[2, 44, 38, 5, 47, 15, 3, 26, 27] ,记录基准值位置应是 2 ,基准值被置换位置为 3 (暂存位置)
循环完后,将基准值置换回真实位置[2, 3, 38, 5, 47, 15, 44, 26, 27],此时 3左边都小于3 右边都大于3
第二轮:拆分成2个数组继续循环处理: [2] 和 [38, 5, 47, 15, 44, 26, 27]
第三轮: [38, 5, 47, 15, 44, 26, 27] 继续获取基准值 38,拆出2个数组 [5,15,26,27] 和[44,47]
依次操作下去... ...
代码示例
// 分区函数,主要实现将数据转移到基准的两边
func partition(arr []int, left, right int) int {
pivot := arr[left] // 默认第一个值为基准值
i := left // 标识基准值应该的位置
ci := left // 被交换的位置
for j := left + 1; j <= right; j++ {
if arr[j] < pivot {
arr[j], arr[i] = arr[i], arr[j]
i++ // 标识基准值应该的位置
ci = j
}
}
// 将基准值置换到真正基准的位置
arr[i], arr[ci] = arr[ci], arr[i]
return i
}
func quickSort(arr []int, left, right int) {
if left > right {
return
}
//获取基准s数据的位置 poivet
poivetIndex := partition(arr, left, right)
quickSort(arr, left, poivetIndex-1)
quickSort(arr, poivetIndex+1, right)
}