西电-算法分析-研究生课程复习笔记
- 24年秋的应该是张老师最后一次用卷面考试,他说以后这节课的期末考试都是在OJ上刷题了
- 张老师上课还挺有意思的,上完之后能学会独立地思考算法设计问题了。整节课都在强调规模压缩这个概念,考试也是考个人对这些的理解,还挺好玩的哈哈
时间复杂度
T ( n ) T(n) T(n) 表示算法在输入规模为 n n n 时的实际运行时间
在实际算法设计中常用以下三种:
- O O O 即“小于等于”,描述 T ( n ) T(n) T(n)的上界。
1 、 n 、 2 n 、 2 n 2 ∈ O ( n 2 ) 1、n、2n、2n^2 \in O(n^2) 1、n、2n、2n2∈O(n2) - Ω Ω Ω 即“大于等于”,描述 T ( n ) T(n) T(n)的下界。
n 2 、 n 3 、 n 10 ∈ Ω ( n 2 ) n^2、n^3、n^{10} \in Ω(n^2) n2、n3、n10∈Ω(n2) - Θ Θ Θ 表示“等于”,表示 T ( n ) T(n) T(n)的上下界一致。
n 2 , 3 n 2 ∈ Θ ( n 2 ) n^2,3n^2 \in Θ(n^2) n2,3n2∈Θ(n2)

主定理求递推式的时间复杂度
T ( n ) = a T ( n b ) + f ( n ) T(n)=aT(\frac{n}{b})+f(n) T(n)=aT(bn)+f(n)
其中 a a a 为归约后的子问题个数, n / b n/b n/b 为归约后子问题的规模, f ( n ) f(n) f(n)为 split 和 merge 子问题的解的工作量。


直接上例题:
-
T ( n ) = 9 T ( n 3 ) + n T(n)=9T(\frac{n}{3})+n T(n)=9T(3n)+n
即 a = 9 , b = 3 , f ( n ) = n , n l o g b a = n 2 a=9,b=3,f(n)=n,n^{log_ba}=n^2 a=9,b=3,f(n)=n,nlogba=n2
因为 f ( n ) = n < n 2 f(n) = n < n^2 f(n)=n<n2,即case 1, T ( n ) = Θ ( n 2 ) T(n)=Θ(n^2) T(n)=Θ(n2) -
T ( n ) = T ( 2 n 3 ) + 1 T(n)=T(\frac{2n}{3})+1 T(n)=T(32n)+1
即 a = 1 , b = 2 3 , f ( n ) = 1 , n l o g b a = 1 a=1,b=\frac{2}{3}, f(n)=1, n^{log_ba}=1 a=1,b=32,f(n)=1,nlogba=1
因为 f ( n ) = = n l o g b a f(n) == n^{log_ba} f(n)==nlogba,即case 2,此时k为0,即 T ( n ) = Θ ( l o g n ) T(n)=Θ(logn) T(n)=Θ(logn) -
T ( n ) = 2 T ( n 4 ) + n 2 T(n)=2T(\frac{n}{4})+n^2 T(n)=2T(4n)+n2
即 a = 2 , b = 4 , f ( n ) = n 2 , n l o g b a = n 0.5 a=2,b=4,f(n)=n^2, n^{log_ba}=n^{0.5} a=2,b=4,f(n)=n2,nlogba=n0.5
因为 f ( n ) > n l o g b a f(n)>nlog_ba f(n)>nlogba,所以是第三种, T ( n ) = Θ ( n 2 ) T(n)=Θ(n^2) T(n)=Θ(n2)
排序
分-治-合并。
老师说的砍规模好像就包括了分和治。
砍规模干活多,则合并时候干活少。反之同理。
二分应用于排序:对于quicksort和mergesort,快排在砍规模时先要让两边各自大于或小于pivot,较麻烦;而合并不需要显式操作,较简单。归并排序在砍规模时直接将数组分成两半,较简单;合并时要进行两个数组的排序和合并,较麻烦。
规模 n 推到规模 n-1应用于排序:选择排序、冒泡排序、插入排序,每次只减少一个问题数量,是较慢的。而这三个排序中,选择排序和冒泡排序每次少一个未排序部分的最值元素,即砍规模时多干活。而插入排序每次少一个当前游标的元素(不一定是最值),而需要在合并时将游标元素在已排序部分插到合适的位置,即合并时多干活。
快排可能会退化,采用随机策略可以避免最坏复杂度为 O ( n 2 ) O(n^2) O(n2)
特殊线性排序不考。
建堆
按照树的形态去砍规模。
砍规模干活多:比如大顶堆,先选一个最大的放在堆顶,然后递归地处理两个子树。相当于规模直接砍半,无显式合并。
T ( n ) = 2 T ( n 2 ) + O ( n ) T(n)=2T(\frac{n}{2})+O(n) T(n)=2T(2n)+O(n),得 T ( n ) = Θ ( n l o g n ) T(n)=Θ(nlogn) T(n)=Θ(nlogn)
砍规模干活少:从最后一个节点开始一下一下砍,直接找最后一个没用的非叶节点即可。合并是将当前子树的根节点向下调整,耗时较长。 T ( n ) = 2 T ( n 2 ) + l o g n T(n)=2T(\frac{n}{2})+logn T(n)=2T(2n)+logn,得 T ( n ) = Θ ( n ) T(n)=Θ(n) T(n)=Θ(n)
Insert:把元素插入到最后一项,再向上调整。(堆排序同理)
如果要动态挑最值,可以用优先队列辅助。
Select
找数组中第k小的元素。
类似快排的partition,数组二分后看topk在哪边。
有种优化策略,将数组先分为多组(每组中奇数个元素),再在每组找个中位数,使用中位数的中位数作为pivot做partition。避免 O ( n 2 ) O(n^2) O(n2)的最坏时间复杂度。
矩阵相乘的二分方法
不考
最大子数组
找和最大的非空连续子数组。
方法1:二分,将数组分为两半,从左半部分、右半部分和跨中间这三部分的子数组中找个最大的。跨中间就是从中点往前面找个最大的后缀、往后边找个最大的前缀,相加就是跨中间的最大子数组。
方法2:DP,每次减少一个问题的规模。用一个全局变量保存历史最大子数组,并保存当前位置之前的子数组情况。如果之前的子数组之和已经为负数,则从当前位置另起一个新子数组。否则扩展之前的子数组到当前为止,即使当前元素为负数,全局变量保存的仍是之前的全局最大子数组。
DP
优化问题用到规模压缩,即DP。
- 刻画最优子结构。列递推式/状态转移方程,能用中文解释。
- 递归定义最优解的值。
- 自下而上计算。原因:需要利用子问题,而多个父问题共享某些子问题,即子问题会被重复的求解。自下而上可以避免重复求解。如果改成自上而下,则需要使用备忘录做记忆化。
有些问题不能用子问题求最优解,比如最长简单路径问题,可能两个最长简单子路径拼起来不是简单路径。
相关问题(计算题):
1. 01背包
思路:穷举是每个物品要么放入要么不放入, O ( 2 n ) O(2^n) O(2n)。如果当前剩余容量为 k,在考虑第 i 个物品是否拿,拿不拿的两种情况,都可以利用 d p [ i − 1 ] [ k ] dp[i-1][k] dp[i−1][k]这个子问题。由于不知道 k 是多少,每次都需要扫描一遍整个容量。
2. 最大子数组
上面写了。
3. LCS最长公共子序列
思路:穷举是 O ( 2 m + n ) O(2^{m+n}) O(2m+n)。如果已知当前游标 i i i 和 j j j 前面的LCS,继而可以得到当前的LCS。即满足最优子结构。 d p dp dp数组起到备忘录的作用。
设 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示序列 X X X 的前 i i i个字符和序列 Y Y Y 的前 j j j 个字符的 LCS 长度。
m, n = len(X), len(Y)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):for j in range(1, n + 1):if X[i - 1] == Y[j - 1]:dp[i][j] = dp[i - 1][j - 1] + 1else:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
4. 矩阵链乘
对于矩阵数组 [ A 1 , A 2 , A 3 ] [A1,A2,A3] [A1,A2,A3]的链乘最小代价,可以通过 [ A 1 , A 2 ] ∗ [ A 3 ] [A1,A2]*[A3] [A1,A2]∗[A3]和 [ A 1 ] ∗ [ A 2 , A 3 ] [A1]*[A2,A3] [A1]∗[A2,A3]的代价得到,利用了 [ A 1 , A 2 ] [A1,A2] [A1,A2]和 [ A 2 , A 3 ] [A2,A3] [A2,A3]这两个子问题。扩展即可知道子问题就是在各个分割点分割之后的子数组,利用子问题的方式就是从子问题中选一个最值。满足最优子结构。
会重复利用较短的子数组,所以自下而上,用个dp数组做备忘录。
5. ALS装配线调度
就是给了两条装配线的进入耗时、出去耗时。然后两条装配线在功能上是相同的,有多个装配站,两条线上同一个下标的装配站是功能相同,但用时可能不同。所以有个切换操作,可以把物品从一条线搬到另一条线,试图加速。所以要求一个物品完成装配花费的最短时间。长的像最短路径,其实因为方向是固定的,所以不是图而是树,问题稍微简单一点。

dp方法见下图。

贪心
如果可以直接知道用哪个子问题也能得到最优解,不用比较各个子问题的结果,就可以贪心、即贪心 ∈ \in ∈DP。
相关问题如:
-
分数背包:优先选单价高的。
-
哈夫曼树:权重越高的字符,编码长度越短。权重越高,越会被后挑选,即越接近根节点。

-
活动选择:多个活动有起止时间,只能选互不冲突的,使活动数量最大化。DP是在当前活动处,找前面最后一个兼容本活动的活动,然后选或者不选,dp[i]是到前i个活动的最多兼容活动数。贪心策略是优先选结束时间早的,为后续活动留下更多时间。
最短路径
重点是确定通过计算次序。
之前的问题都是可以转化为一棵树,子问题向上扩展,最终得解。
而b->c、c->b都有可能,即c可以利用b之前的最短路径、b也可以利用c之前的最短路径。所以不能是一棵向上的树。所以需要确定一个计算次序,即谁是子问题。
Dijkstra
在无负权环的时候,这个计算次序是有的。他是子问题找父问题,即找一个最近的节点。如果有负权环,则有些很远节点的距离反而越来越近,计算次序就出现问题了。通过计算次序理解为什么是dp。
Bellman-ford
允许负权环,所以没有计算次序,所以迭代多轮来补偿。单源。个人感觉就是Floyd的单源形式。
SPFA就是如果有些点被更新后,才加入队列进行后续的松弛更新。
如果第V次还能松弛,说明有负权环。
Floyd
多源。 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k],已知未使用 k 时,i 到 j 的最短路径,看用 k 是否能继续缩短。
时间复杂度
floyd是 O ( V 3 ) O(V^3) O(V3)。
迪杰斯特拉是每次找一个最近的点,然后基于这个中转点更新源点到中转点的邻点。所以对于邻接矩阵的实现,是V的循环里套个找邻点的V, O ( V 2 ) O(V^2) O(V2)
Bellman-ford是重复V-1次,然后松弛所有边,所以是 O ( V ∗ E ) O(V*E) O(V∗E)
搜索
无法用规模压缩,只能蛮力穷举。
设定边界减少不必要的搜索。
限界函数:杀死更多的节点、效率。
NP问题
P可以在多项式时间内求解,NP只能在多项式问题内验证解。

NPC(理论上可解,穷举):circuit-sat(电路可满足)、TSP(旅行商)、3-color三色(平面图染三色,使得相邻区域颜色不同)、哈密尔顿路径。
不可判定:Hilbert’s Tenth Problem(希尔伯特第十问题)、Halting Problen(停机问题)、Post Correspondence Problem(PCP)、Program Equivalence Problem(程序等价性问题)、Optimal Data Compression Problem(最优数据压缩问题)、Virus Identification Problem(病毒识别问题)、多元多项式整数根(费马大定理)、普斯特对应问题
相关文章:
西电-算法分析-研究生课程复习笔记
24年秋的应该是张老师最后一次用卷面考试,他说以后这节课的期末考试都是在OJ上刷题了张老师上课还挺有意思的,上完之后能学会独立地思考算法设计问题了。整节课都在强调规模压缩这个概念,考试也是考个人对这些的理解,还挺好玩的哈…...
编译时找不到需要的库,如何在PyCharm中为你的项目添加需要的库
丰富的库支持是 Python 语言的一大特点,但是在使用 PyCharm 进行Python 代码编译的时候,遇到一些需要使用到的库提示不能解析时,该如何添加呢? 比如下图所示的代码,可以看到需要使用 selenium、b4、jieba 这些库&…...
ip addr 命令给Linux网络接口配置多个IP地址值
问一下Chatgpt 怎么使用ip addr 命令给Linux网络接口配置多个IP地址值 根据Chatgpt的提示执行了命令,命令执行成功,看下执行结果。 ifconfig 命令查看接口IP地址 ip addr show 命令查看接口IP地址...
C#语言的数据库编程
C#语言的数据库编程 在现代软件开发中,数据库是不可或缺的一部分。无论是企业级应用还是个人项目,数据的存储与管理都是程序的核心功能之一。C#作为一种强类型、面向对象的编程语言,广泛应用于Windows平台的开发,尤其是在构建与数…...
时频分析之S变换
S变换的提出 1996年,由R.G Stockwell 提出了S变换,和其他时频分析工具一样,通过S变换,我们可以同时从时域以及频域观察一个信号的能量分布。S变换融合了短时傅里叶变换和小波变换的优点。关于S变换,最早发表于TSP上的…...
第二十八周学习周报
目录 摘要Abstract1 GFPGAN1.1 总体结构1.2 实验研究1.3 代码分析 总结 摘要 本周主要的学习内容是GFPGAN模型。GFPGAN是一种基于生成对抗网络(GAN)的模型,其利用封装在预训练的人脸GAN中的丰富多样的先验进行人脸图像的修复。这种生成面部先验(GFP&…...
SurfaceFlinger MessageQueue原理
SurfaceFlinger MessageQueue 有2个作用: 处理SurfaceFlinger INVALIDATE、REFRESH事件管理SurfaceFlinger主线程挂起和恢复 SurfaceFlinger::run() { while (true) { mEventQueue->waitMessage(); } } waitMessage {do {IPCThreadState::self()->flushComm…...
component-动态控制 div width 的值 根据传入的变量决定width的值 vue
1.实现 根据参数的值,div显示不同的长度 <div class"node-line" :style"lineProgress"></div> <script>export default {name: "trainSummaryInfo",data(){return{linePercentage:200,}},computed:{lineProgress…...
C#中的常用集合
目录 一、动态数组ArrayList 二、List 三、栈(Stack) 四、队列(Queue) 五、字典(Dictionary),int> 一、动态数组ArrayList ArrayList 是 C# 中提供的一种动态数组类,位于命名空间 Syste…...
插入实体自增主键太长,mybatis-plaus自增主键
1、问题 spring-boot整合mybtais执行insert语句时,主键id为长文本数据。 2、分析问题 1)数据库主键是否自增 2)数据库主键的种子值设置的多少 3、解决问题 1)数据库主键设置的时自增 3)种子值是1 所以排查是数据库的问题 4、继…...
晨辉面试抽签和评分管理系统之一:考生信息管理和编排
晨辉面试抽签和评分管理系统(下载地址:www.chenhuisoft.cn)是公务员招录面试、教师资格考试面试、企业招录面试等各类面试通用的考生编排、考生入场抽签、候考室倒计时管理、面试考官抽签、面试评分记录和成绩核算的面试全流程信息化管理软件。提供了考生…...
【MySQL】MVCC详解, 图文并茂简单易懂
欢迎来到啊妮莫的学习小屋 祝读本文的朋友都天天开心呀 目录 MVCC简介快照读与当前读快照读当前读 隔离级别隐藏字段和Undo Log版本链✨MVCC原理--ReadView✨ReadView简介设计思路适用隔离级别重要内容 ReadView规则MVCC整体流程 不同隔离级别下的MVCC读已提交可重复读 总结 M…...
中国数字化发展的问题与机会
橙蜂智能公司致力于提供先进的人工智能和物联网解决方案,帮助企业优化运营并实现技术潜能。公司主要服务包括AI数字人、AI翻译、埃域知识库、大模型服务等。其核心价值观为创新、客户至上、质量、合作和可持续发展。 橙蜂智农的智慧农业产品涵盖了多方面的功能,如智能化推荐、…...
【ROS2】☆ launch之Python
☆重点 ROS1和ROS2其中一个很大区别之一就是launch的编写方式。在ROS1中采用xml格式编写launch,而ROS2保留了XML 格式launch,还另外引入了Python和YAML 编写方式。选择哪种编写取决于每位开发人员的爱好,但是ROS2官方推荐使用Python方式编写…...
如何稳定使用 O1 / O1 Pro,让“降智”现象不再困扰?
近期,不少朋友在使用 O1 或 O1 Pro 模型时,都会碰到“降智”或“忽高忽低”的智力波动,比如无法识图、无法生成图片、甚至回答准确度也不稳定。面对这些问题,你是不是也感到头疼呢? 为了找到更可靠的解决办法…...
zookeeper监听机制(Watcher机制)
文章目录 引言I zookeeper监听机制Watcher机制实现分布式的通知功能触发事件种类Watcher的三个过程II watch机制特点一次性触发事件封装event异步发送先注册再触发常见的通知状态和事件类型III 应用案例(Kafka)Kafka的消息模型Kafka在Zookeeper中保存的元数据Kafka 基于Contr…...
docker 启动 nacos 单机模式
docker 启动 nacos 单机模式 # 拉取镜像# 启动,如果不拉镜像会自动拉取最新的 image docker run --name standalong_nacos -p 8848:8848 -p 9848:9848 -p 9849:9849 -e MODEstandalone -d nacos/nacos-server# 状态查看外部访问验证 输入部署的 docker ip 地址以及…...
学习threejs,导入babylon格式的模型
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.BabylonLoader babyl…...
03.MPLS静态LSP配置实验
MPLS静态LSP配置实验 1、实验环境2、基础配置开启全局mpls接口下开启mpls配置静态LSP配置FEC从1.1.1.1到3.3.3.3配置FEC从3.3.3.3到1.1.1.13、信息查看查看LFIB表(标签转发信息表)查看FIB表(转发信息表)查看详细FFIB表tracert lsp iptracert -vping lsp ip4、抓包验证1、实…...
程序血缘分析技术在工商银行软件工程中的应用
当前,随着软件领域技术更新换代速度的日益加快,市场需求也变得更加多样化和个性化,业界普遍通过加速产品迭代来满足客户需求,但在此过程中也暴露出一些研发管理痛点问题,如服务和程序类资产信息分散于各个不同的应用和系统中,信息归集费时费力;设计、开发和测试人员无法…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
轻量级Docker管理工具Docker Switchboard
简介 什么是 Docker Switchboard ? Docker Switchboard 是一个轻量级的 Web 应用程序,用于管理 Docker 容器。它提供了一个干净、用户友好的界面来启动、停止和监控主机上运行的容器,使其成为本地开发、家庭实验室或小型服务器设置的理想选择…...
从零手写Java版本的LSM Tree (一):LSM Tree 概述
🔥 推荐一个高质量的Java LSM Tree开源项目! https://github.com/brianxiadong/java-lsm-tree java-lsm-tree 是一个从零实现的Log-Structured Merge Tree,专为高并发写入场景设计。 核心亮点: ⚡ 极致性能:写入速度超…...
【版本控制】GitHub Desktop 入门教程与开源协作全流程解析
目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork(创建个人副本)步骤 2: Clone(克隆…...
