大三落汤狗の算法笔记 (持续更新)
1. 算法复杂度分析
简便:复杂度取阶数最高项,去系数。如:O(3n²+2n+1)=O(n²)
O()低阶/o(),Ω()高阶/w(),θ()同阶
阶关系成立:自反OΩθ/对称θ/传递OoΩwθ
O(f)+O(g)=O(max(f,g))
O(f)+O(O(f))=O(f)
O(递归)
迭代法:
n次计算,每次O(单次)求和
eg: 求n!
- 求退出条件:T(1)=1
- 求递推公式:T(n) = T(n-1)+1
- 展开递推公式:= T(n) = T(n-1)+1 = T(n-2)+1+1 = ... = T(1)+n-1 = O(n)
Master法:
T(n)=aT(n/b)+f(n)的渐进阶:
\({n^{log_b a}}\) > f(n): 前者\({O(n^{log_b a})}\)
\({n^{log_b a}}\) = f(n): 相乘\({O(n^{log_b a} * log n)}\)
\({n^{log_b a}}\) < f(n): 后者\({O(f(n))}\)
https://zhuanlan.zhihu.com/p/113406812
2. 分治
- 可均等地划分为子问题
- 可合并
- 子问题间互相独立
- 适合分治的问题,会出现可重复利用的已计算元素,以降低复杂度
复杂性分析:
https://blog.csdn.net/LeungSr/article/details/115912946
递归
- 结构:二叉树
- 优点:短小精悍
- 缺点:比非递归,有栈空间,计算会更慢点(复杂逻辑中)
- 汉诺塔,全排列
8枚硬币,有一枚轻的假币
3次分2:二分法,{4,4} > {{2,2}{2,2}} > {{{1,1}...}}
2次分3:引入等于,{3,3,2} > {{1,2}{1,2}{2}}/{3,3,{1,1}}
汉诺塔:
def hanoi(n,a,b,c):
# a has n, b&c init 0, a move to b
if n==0:
return
else:
hanoi(n-1,a,c,b)
moveOne(a,b)
hanoi(n-1,c,b,a)
全排列:
list=[1,2,3,4]
def Arrange(list,k,m):
if k==m:
print(list)
else:
for i in range(k,m+1):
swap(list[k],list[i]) # [k(i0),i1,i2,i3] -> [1,2,3,4] -> [2,1,3,4] -> [2,1,4,3] ->
Arrange(list,k+1,m) # 向右缩小子问题,[1,[2,3,4]] -> [1,[2,[3,4]]]
swap(list[k],list[i]) # 复原
快速排序
发明背景:https://zhuanlan.zhihu.com/p/392380569
快排最坏O(n^2):锚点总是选头部/尾部,[0,1,2,...]→0,[1,2,...]→扫描n个元素,重复扫描n次
大整数乘法
n位数 乘 n位数
T(n)=4T(n/2)+f(n) = O(n^1.59)
每次分解:4个苹果Apple,2个篮子Basket,一人背一个篮子,如何减轻重量 (a↓,b↑)
虽然2分,但前面系数4代表要乘4次,是主要复杂度的来源,log_2 4=2,仍然是O(n^2)
此处考虑如何降系数
因式分解,利用已计算的值加速计算
Strassen 矩阵乘法
省流:本质因式分解重组,降低乘法(系数)次数,O(n^2.81) = 8T(n/2)+O(n^2) → 7T(n/2)+O(n^2) = O(n^2.81)
原O(n^3),太慢了
每个'+'都是n^2/4次加法
再优化:b=2x2的分解不能再降乘法次数了,应当研究3x3或5x5的分解? (a↓,b↑)
目前公认:\({O(n^{2.376})}\)
更优?最新机器学习论文:https://zhuanlan.zhihu.com/p/406089914
L型棋盘覆盖
特定:\({2^n * 2^n}\)的棋盘,因为 2^n % 3 = 1 恒成立
选:k阶数,n格子数
数独:
循环赛日程表,运动员比赛问题
https://www.cnblogs.com/crx234/p/5988418.html
需要多少天:n-1
动态规划
时间复杂度O(行x列):看表格有多大,都忙着填表
问题可分解,代价函数生成状态表,状态表的值被(跨级)重复利用
分治:用了递归,从0~n都得运行一遍
DP:0~n,我只运行我最优解所需要的
最长公共子序列
初始值0
=↘ | ≠↓ |
---|---|
≠→ | 当前 |
传播方向+单调性?
4 | 2 |
---|---|
3 | 5 |
不可能出现以上的情况,由于不等时一定会向右向下传递,一定是单调递增,所以最坏情况应是
1 | 2 |
---|---|
3 | 3或1 |
假设a=“1234”,b=“243”,则最长子序列="24"
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 |
1 2 |
0 | 0 | 1 2 |
→1 | →1 |
2 4 |
0 | 0 | ↓1 | →1 | ↘2 24 |
... |
背包
数组大小bag[n][C+1](背包空间从0开始时)
矩阵乘法
https://www.cnblogs.com/mozi-song/p/9629137.html
k:在哪个数后分割
求A1,6:所以k记录的是在哪个数后分割((...)k(...))
i <j时,dp[i][j] = min{dp[i][k] + dp[k+1][j] + pi-1pkpj}, k = i...j-1 (p为各个矩阵的秩,见题目一节)
在此题中,我们可以选择用一个同样的二维矩阵s[][]来记录后者,其中s[i][j]中记录Ai...Aj的分割分界线k。for(int k = i; k < j; k++){
s[i][j] = k;
所以看结果的时候,↙,然后一层层地看
eg: 先在A3后切一刀,然后在A1,A5后切一刀 (A1(A2A3))((A4A5)A6)
特征
下列哪一个不是动态规划算法的特征:
正确答案: D 我的答案: C
A. 问题具有最优子结构性质
B. 子问题重叠(减少重复计算)
C. 最优值的定义是递归的(递推公式)
D. 以自顶向下的方式计算最优值(自底向上)
B: 木头太短,切一刀或不切
C: 木头太长,Ri+RN-i,错在-M,应为-i
max(dp[j], dp[j - len[i]] + cost[i])
贪心
特征
-
最优子结构
-
贪心选择
-
子问题耦合,较为复杂,一般不可再分
与dp区别
贪心容易先退出,求不出最优解
哈夫曼编码
哈夫曼树(最优树):https://zhuanlan.zhihu.com/p/415467000
树的带权路径长度WPL, WeightPathLen:所有叶子结点的带权路径长度之和
最优前缀码
其集合内,最优前缀码间不能相互包含
回溯
特征
进,换,退
步骤
- 定义问题的解空间
- 确定易于搜索的解空间的结构[树/图]
- 深度优先搜索+剪枝函数(非最优解)/条件(非可行解)
解空间
包含所有可能解,存在一个最优解
子集树
当所给的问题是从n个元素的集合S中找到S满足某种性质的子集时相应的解空间树称为子集树。例如0-1背包问题,这类问题有 $ 2^n $ 个叶结点,总结点个数 $ 2^{n+1}-1 $ ,遍历子集树需要Ω(2^n)的计算时间。
排列树
40选择题
给定一个变长码的表,这些变长码互相不为前缀
eg:0, 01, 011❌ 0, 10, 111 ✔
箱子装载,贪心
int Backtrack(int t){
if(t>n){
if(cw>bestw){//当前叶子结点对应的解更优
for(int j=1;j <= n;j++) bestx[j]=x[j];
bestw=cw;
}
return 1;
}
r -= w[t];/*搜索左子树*/
if(cw+w[t] <= c){//满足约束
x[t]=1; cw+=w[t]; Backtrack(t+1); cw -= w[t];
}
if(cw+r>bestw){/*搜索右子树*/
x[t]=0; Backtrack(t+1);
}
r+=w[t];
return 1;
}
可行性约束、上界函数
三角形+-
背包问题
最大团
{1,2},只拎出来1、2和点的相关直线,发现{1,2}是G的一部分图,是完全子图
{1,2,5}{1,4,5}...找不到更大的
{2,4},只拎出来这2个点,发现它们之间没有任何直线相连,空子图
极大团是增加任一顶点都不再符合定义的团
任意(点u,点v)有边(u,v)
∈E……:每2个点都得有联系
错题
回溯法常用剪枝函数来减少对解空间树的搜索,剪枝函数包括()。
正确答案: C 我的答案: C
A.最大函数和最小函数
B.约束函数和最优函数
C.约束函数和限界函数
D.限界函数和最优函数
2[单选题]问题的解空间一般用树形式来组织,解空间树的类型包括()。
正确答案: D 我的答案: D
A.二分搜索树和B-树
B.B-树和B+树
C.子集树和B-树
D.子集树和排列树
3[单选题]当所给的问题是确定n个元素满足某种性质的排列时,相应的解空间树称为排列树。排列树问题复杂性通常是( )。
正确答案: D 我的答案: D
A.O(n)
B.O(\(2^n\))
C.O(n²)
D.O(n!)
4[单选题]当所给的问题是从n个元素的集合S中找出满足某种性质的子集时,相应的解空间树称为子集树。子集树问题复杂性通常是()。
正确答案: B 我的答案: C
A.O(n)
B.O(\(2^n\)) 满二叉树
C.O(n²)
D.O(n!)
https://www.cnblogs.com/zuofaqi/p/9926519.html
5[单选题]对比回溯法与深度优先遍历,以下说法不正确的是()。
正确答案: A 我的答案: A
A.两者在实现上都遵循深度优先,访问序一样。
B.深度优先遍历不含剪枝。
C.很多回溯算法采用剪枝技术。
D.深度优先遍历对所有顶点仅访问一次,回溯法可以多次访问顶点。
分支限界法
先算最优解,再逆推最优解怎么出来的
上课没听 https://blog.csdn.net/weixin_44712386/article/details/105532881
队列式分支限界法
优先队列:有优先级 https://www.cnblogs.com/huanxiyun/articles/5396147.html
先后顺序影响结果:解空间用树
结构
平面地图,没有先后顺序:解空间用维度有限的向量