学习路径:
阶段一:算法入门
- 我们需要
熟悉各种数据结构的特点和用法
,学习不同算法的原理、流程、用途和效率等方面的内容。
阶段二:刷算法题
- 建议从热门题目开刷,先积累至少 100 道题目,熟悉主流的算法问题。初次刷题时,
“知识遗忘”
可能是一个挑战,但请放心,这是很正常的。我们可以按照“艾宾浩斯遗忘曲线”
来复习题目,通常在进行 3~5 轮的重复后,就能将其牢记在心。
阶段三:搭建知识体系
2025年6月15日...小于 1 分钟
熟悉各种数据结构的特点和用法
,学习不同算法的原理、流程、用途和效率等方面的内容。“知识遗忘”
可能是一个挑战,但请放心,这是很正常的。我们可以按照“艾宾浩斯遗忘曲线”
来复习题目,通常在进行 3~5 轮的重复后,就能将其牢记在心。维度 | 说明 |
---|---|
运行效率 | 时间复杂度尽量低、操作尽量少 |
就地性 | 在原数组上直接操作实现排序,无须借助额外的辅助数组 |
稳定性 |
排序后`相等元素在数组中的相对顺序不发生改变 |
自适应性 | 自适应排序的时间复杂度会受输入数据的影响(最佳时间复杂度、最差时间复杂度、平均时间复杂度并不完全相等) |
是否基于比较 | 基于比较的排序依赖比较运算符(<=>)来判断元素的相对顺序从而进行排序,理论最优时间复杂度为 O(nlogn)。 非比较排序不使用比较运算符,时间复杂度可达 O(n) ,但其通用性相对较差。 |
遍历
数据结构的每个元素广度、深度优先搜索
:适用于树和图有序性
,每轮缩小一半搜索范围
,直至找到目标元素或搜索区间为空为止。nums[m]
和 target
的大小关系,分为以下三种情况:
nums[m] < target
时,说明 target
在区间 [m+1,j] 中,因此执行 i=m+1 。nums[m] > target
时,说明 target
在区间 [i,m−1] 中,因此执行 j=m−1 。nums[m] = target
时,说明找到 target
,因此返回索引 m 。int
类型,因此 i+j 可能会超出 int
类型的取值范围。为了避免大数越界,我们通常采用公式 m=⌊i+(j−i)/2⌋ 来计算中点队列
来实现。队列遵循先进先出
的规则,而广度优先遍历则遵循逐层推进
的规则/* 层序遍历 */
func levelOrder(root *TreeNode) []any {
// 初始化队列,加入根节点
queue := list.New()
queue.PushBack(root)
// 初始化一个切片,用于保存遍历序列
nums := make([]any, 0)
for queue.Len() > 0 {
// 队列出队
node := queue.Remove(queue.Front()).(*TreeNode)
// 保存节点值
nums = append(nums, node.Val)
if node.Left != nil {
// 左子节点入队
queue.PushBack(node.Left)
}
if node.Right != nil {
// 右子节点入队
queue.PushBack(node.Right)
}
}
return nums
}
利用了函数栈实现
f(n) = f(n-1) + 1;
f(n) = f(n-1) + f(n-2);
f(n) = n*f(n-1);
思想:它通过设置一些具有有限数量、大小顺序的桶,每个桶对应一个数据范围,将数据平均分配到各个桶中;然后,在每个桶内部分别执行排序;最终按照桶的顺序将所有数据合并
稳定排序、非原地排序,需要借助k个桶和n个元素的数组
非比较排序算法
算法流程:条件 一个长度为 n 的数组,其元素是范围 [0,1) 内的浮点数
桶排序的优化:
图解:
代码:
/* 桶排序 */
func bucketSort(nums []float64) {
// 初始化 k = n/2 个桶,预期向每个桶分配 2 个元素
k := len(nums) / 2
buckets := make([][]float64, k)
for i := 0; i < k; i++ {
buckets[i] = make([]float64, 0)
}
// 1. 将数组元素分配到各个桶中
for _, num := range nums {
// 输入数据范围为 [0, 1),使用 num * k 映射到索引范围 [0, k-1]
i := int(num * float64(k))
// 将 num 添加进桶 i
buckets[i] = append(buckets[i], num)
}
// 2. 对各个桶执行排序
for i := 0; i < k; i++ {
// 使用内置切片排序函数,也可以替换成其他排序算法
sort.Float64s(buckets[i])
}
// 3. 遍历桶合并结果
i := 0
for _, bucket := range buckets {
for _, num := range bucket {
nums[i] = num
i++
}
}
}