算法与数据结构总览
知识体系
数据结构
数据以某种特定结构进行存储
- Array
- Stack/Queue
- Priority Queue(Heap)
- LinkedList(single/double)
- Tree/Binary Tree
- Binary Search Tree
- HashTable
- Disjoint Set
- Trie
- BloomFilter
- LRU Cache
算法
- General Coding
- In-order/Pre-oder/Post-order traversal
- Greedy
- Recursion/Backtrace
- Breadth-first search
- Depth-firsh search
- Divide and Conquer
- Dynamic Programming
- Binary Search
- Graph
算法复杂度
O(1) :常数级复杂度,记为O(1)
int a = 10
print(a)
O(log n):对数复杂度
for (int i=1; i<n; i=i*2) {
print(i)
}
O(n):线性复杂度
for (int i=1; i<n; i++) {
print(i)
}
O(n log n):线性对数复杂度
for (int i=1; i<n; i++) {
for (int j=1; j<n; j=j*2) {
print(j)
}
}
O(n^2):平方复杂度
for (int i=1; i<n; i++) {
for (int j=1; j<n; j++) {
print(j)
}
}
O(2^n):指数复杂度
for (int i=1; i<Math.pow(2, n); i++) {
print(i)
}
O(n!):阶乘复杂度
def factorial(n)
if n == 0 or n == 1:
return n
return n*factorial(n-1)
排序
概念
输入:n个记录R1,R2,…,Rn,对应的关键字为k1,k2,…,kn。
输出:输入序列的一个重排R1,R2
,…,Rn,使得k1
≤k2≤k3
≤…≤kn`
稳定性
如果待排序表中的两个元素Ri,Rj,其对应的关键字keyi=keyj,且在排序前Ri在Rj前面。如果使用某一排序算法后,Ri仍然在Rj前面,则说明该算法是稳定的,反之是不稳定的。
内部排序
内部排序指在排序期间元素全部存放在内存中进行排序
外部排序
外部排序指排序期间元素无法全部同时放在内存中,必须在排序过程中根据要求数据需要在内外存之间移
常见排序算法复杂度
算法名称 | 最好情况条件 | 最好情况 | 最坏情况条件 | 最坏情况 | 平均情况 | 空间复杂度 | 是否稳定 |
---|---|---|---|---|---|---|---|
直接插入排序 | 数列从小到大 | O(n) | 数列从大到小 | O(n^2) | O(n^2) | O(1) | 是 |
冒泡排序 | 数列从小到大 | O(n) | 数列从大到小 | O(n^2) | O(n^2) | O(1) | 是 |
简单选择排序 | 无 | O(n^2) | 无 | O(n^2) | O(n^2) | O(1) | 否 |
希尔排序 | 无 | 无 | 无 | 无 | O(1) | 否 | |
快速排序 | 每次选中位数 | O(n log n) | 每次选最大/最小 | O(n^2) | O(n^2) | O(log n)/O(n) | 否 |
堆排序 | 无 | O(n log n) | 无 | O(n log n) | O(n log n) | O(1) | 否 |
2-路归并排序 | 无 | O(n log n) | 无 | O(n log n) | O(n log n ) | O(n) | 是 |
基数排序 | 无 | O(d(n+r)) | 无 | O(d(n+r)) | O(d(n+r)) | O(r) | 是 |
希尔排序的时间复杂度依赖于增量函数,所以无法给定确定的时间复杂度
排序算法建议
- 若n较小(n<=50),则可以采用直接插入排序或者简单选择排序
- 文件的初始状态已经按关键字基本有序,则选用直插或冒泡
- 若n较大时,则应采用时间复杂度为O(nlogn)的排序方法:快排,堆排序或归并排序。快排被认为目前基于比较的内部排序算法中最好的算法,当待排序的关键字是随机分布的,快排的平均时间最短
算法练习
练习网站
leetcode
解题方式
- 明确题目意思,观察是否有坑(空字符串、非法数字)
- 尽可能多给出解法,找出最优解(时间、空间复杂度)
- 练习大量的题目