当前位置: 首页 > news >正文

山东大学算法设计与分析复习笔记

名词解释

O、Ω、θ的定义(渐近复杂度符号)

  • O(Big O):表示上界,说明算法的复杂度不超过某个函数,定义为:
    若存在正数常数c,n0​,使当n≥n0时,有

                T(n)≤c⋅f(n)

                则记为:T(n)=O(f(n))

  • Ω(Omega):表示下界,说明算法的复杂度至少是某个函数,定义为:
    存在正数常数c,n0,使当n≥n0时,有

                T(n)≥c⋅f(n)

                则记为:T(n)=Ω(f(n))

  • θ(Theta):表示紧确界,算法的复杂度是f(n)的渐近界:
    存在正数常数c1,c2,n0​,使当n≥n0​时,有

                c1⋅f(n)≤T(n)≤c2⋅f(n)

                则记为:T(n)=Θ(f(n))

P、NP、NPC问题的定义以及归约的定义

 归约问题

将3SAT问题归约到团问题

3SAT问题定义

  • 输入:一个由若干子句(clauses)构成的布尔逻辑表达式(合取范式,CNF),其中每个子句恰好包含3个文字(literal,即变量或其否定)。
    示例

    (x1∨¬x2∨x3)∧(¬x1∨x4∨¬x5)∧(x2∨x3∨¬x4)
  • 问题:是否存在一组对变量的赋值(真/假),使得整个表达式为真(所有子句均被满足)?

团问题定义:
给定一个无向图G=(V,E)和整数k,判断是否存在大小为k的完全子集(即团)。

  • 归约构造
    设3-SAT实例有 m 个子句 C1,C2,…,Cm每个子句含3个文字。构造图 G:

    • 顶点:为每个子句 Ci中的每个文字创建一个顶点(如子句 (x1∨¬x2∨x3)对应顶点 vi1,vi2,vi3​)。

    • :连接不同子句的顶点,除非它们互为否定(如 x1 和 ¬x1​ 无边)。

  • 参数设置:令 k=m(子句数)。

  • 正确性证明

    • 若3-SAT可满足:存在赋值使每个子句至少一个文字为真。从每个子句选一个真文字对应的顶点,构成集合 V′。因不同子句的顶点无边当且仅当冲突,而赋值无冲突,故 V′ 中任意两点有边 → 形成大小为 k=m的团。

    • 若 G 有大小为 k=m 的团:团中顶点来自不同子句(因同子句内无边)。选择这些顶点对应的文字赋值为真,无冲突(因无边仅存于非互斥文字间) → 满足所有子句。

  • 结论:团问题 ∈ NP,且3-SAT ≤ₚ 团问题 → 团问题是NP完全问题(依据PPT中“若X是NP完全且X≤ₚY,则Y是NP完全”)。

将团问题规约到顶点覆盖问题

  • 归约构造

    • 给定团问题实例 (G,k),构造其补图 Gˉ=(V,Eˉ)(Eˉ包含所有 G 中不存在的边)。

    • 设顶点覆盖实例为 (Gˉ,∣V∣−k)

  • 正确性证明

    • 若 G 有大小为 k 的团 V′
      在 Gˉ中,V′ 内任意两点无边 → Gˉ 的每条边至少有一个端点不在 V′ → V∖V′ 覆盖 Gˉ 的所有边,且 ∣V∖V′∣=∣V∣−k。

    • 若 Gˉ有大小为 ∣V∣−k的顶点覆盖 C
      则 V∖C在 Gˉ 中无边 → 在 G 中 V∖C 内任意两点均有边 →V∖C 是 G 的大小为 k 的团。

  • 归约时间:构造补图 Gˉ 需 O(∣V∣2)时间(检查所有顶点对),是多项式时间。

结论:顶点覆盖问题 ∈ NP,且团问题 ≤ₚ 顶点覆盖问题 → 顶点覆盖问题是NP完全问题(依据归约传递性)。

将团问题规约到子图同构问题

子图同构问题:
给定两个图G1​和G2​,判断是否存在一个顶点映射,使得G1​保持结构地“同构”到G2​的子图。

  1. 给定团问题实例

    • 图 G=(V,E)

    • 目标团大小 k

  2. 构造子图同构实例

    • 令 H为完全图 Kk(即 k 个顶点,两两相连)。

    • 问题转化为:判断 H 是否是 G 的子图同构

证明

  • 若 G有大小为 k 的团

    • 则该团本身就是一个完全图 Kk,与 H 同构。

    • 因此,子图同构问题的答案为“是”。

  • 若 H 是 G 的子图同构

    • 则 G 必须包含 k 个顶点,两两相连,即构成一个团。

    • 因此,原团问题的答案为“是”。

结论

Clique(G,k)  ⟺  SubgraphIsomorphism(G,Kk)Clique(G,k)⟺SubgraphIsomorphism(G,Kk​)

即,团问题可以归约到子图同构问题。

贪心算法正确性证明 

1. 定义贪心选择策略(如:选结束最早的活动/单位价值最高的物品)。
2. 证明贪心选择性质:
   - 设 S 是不含贪心选择 a 的最优解。
   - 构造 S' = (S - {b}) ∪ {a}(b 是 S 中某个元素)。
   - 证明 S' 可行且价值 ≥ S。
3. 证明最优子结构:
   - 设原问题最优解为 {a} ∪ S_sub。
   - 若 S_sub 不是子问题最优解,则存在更优解 S_sub',导致 {a} ∪ S_sub' 优于原解,矛盾。
4. 由数学归纳法:算法每一步均保持最优性。

 计算最大流

 

计算时间复杂度

 

分治例题

归并排序伪代码

function merge_sort(arr):if length(arr) <= 1:return arrmid = length(arr) // 2left = arr[0:mid]right = arr[mid:]// 递归排序左右子数组sorted_left = merge_sort(left)sorted_right = merge_sort(right)// 合并两个已排序数组return merge(sorted_left, sorted_right)function merge(left, right):result = []i = 0j = 0while i < length(left) and j < length(right):if left[i] <= right[j]:result.append(left[i])i += 1else:result.append(right[j])j += 1// 复制剩余元素while i < length(left):result.append(left[i])i += 1while j < length(right):result.append(right[j])j += 1return result

寻找一个序列中倒置(inversions)的数量,若前面的数比后面的数大,就形成一个倒置,例如74385中有74,73,75,43,85五个(具体案例记不清了,大概是这些数),参考归并排序算法,写出基本思想,伪代码,时间复杂度

  1. 分治:将序列分成左右两半,递归计算左半部分的倒置数和右半部分的倒置数。

  2. 合并:在合并左右两部分时,如果左半部分的某个元素 A[i] 大于右半部分的某个元素 A[j],则 A[i] 及其后面的所有左半部分元素都会与 A[j] 形成倒置(因为左右部分已经分别有序)。

    • 因此,倒置数可以增加 mid - i + 1(其中 mid 是左半部分的最后一个位置)。

这种方法的时间复杂度为 O(n log n),与归并排序相同。

function countInversions(A):n = length(A)if n <= 1:return 0  // 单个元素无倒置mid = n // 2left = A[0..mid-1]right = A[mid..n-1]inversions = countInversions(left) + countInversions(right)  // 递归计算左右部分的倒置inversions += mergeAndCount(A, left, right)  // 合并并统计跨越左右的倒置return inversionsfunction mergeAndCount(A, left, right):i = j = k = 0inversions = 0while i < length(left) and j < length(right):if left[i] <= right[j]:A[k] = left[i]i += 1else:A[k] = right[j]inversions += (length(left) - i)  // 左半剩余元素均与 right[j] 形成倒置j += 1k += 1// 处理剩余元素while i < length(left):A[k] = left[i]i += 1k += 1while j < length(right):A[k] = right[j]j += 1k += 1return inversions

 最大子数组

DP问题

钢条切割问题

自底向上的记忆化搜索并记录每次最优解的切割点为s

 矩阵链乘法

通过动态规划自底向上计算所有可能的矩阵链分割方式,选择乘法代价最小的分割点,逐步构建最优解。枚举所有长度的矩阵链下,遍历选择代价最小的分割点并记录.

  • m[i,k]:左子链 Ai…Ak​ 的最小代价。

  • m[k+1,j]:右子链 Ak+1…Aj的最小代价。

  • pi−1pkpj:合并左右子链的代价(即两个结果矩阵相乘的代价)。

最大公共子序列问题

 

贪心例题

01背包

 活动选择问题

选择局部最优即每次选择结束时间最早的活动,就能剩下更多时间给后面活动选择.

时间复杂度O(n+nlgn)->O(nlgn) 将活动按结束时间递增排序

注意检查合法性

 单源最短路径问题

迪杰斯特拉算法

  1. 维护一个优先队列(最小堆),每次选择当前距离 s 最近的未访问顶点 u(即 u.d 最小)。

  2. 松弛(Relax)操作:对 u 的所有邻接顶点 v,检查是否可以通过 u 缩短 v 到 s 的距离(即 v.d>u.d+w(u,v) 时更新 v.d)。(u.Π是前驱节点)

  3. 逐步扩展已确定最短路径的集合 S,直到所有顶点被处理。

 贝尔曼福德算法

记住n-1次松弛,如果第n次还能松那就是有负权边

所有顶点对之间的最短路

按边数分解的(基于矩阵乘法的)动态规划算法

  1. 计算 D[1] = W(初始权重矩阵)。
    • 通过类似矩阵乘法的方式,计算 D[2] = D[1] * D[1]D[4] = D[2] * D[2],直到 D[m](其中 m ≥ n-1)。

    • 每次“乘法”操作的时间复杂度是 O(n³),共进行 O(log n) 次,总时间复杂度 O(n³ log n)

  2. 检测负权环

    • 计算 D[n],如果 D[n] != D[n-1],说明存在负权环(因为最短路径可以无限绕环降低权重)。

 Floyd-Warshall 算法(按顶点编号分解)

循环1-n作为中间节点时,对矩阵进行松弛更新

 矩阵更新D(1)表示允许以1作为中间节点时的矩阵

 近似算法

 Makespan(负载均衡)问题
  • 问题描述:将 nn 个任务分配到 mm 台机器上,最小化所有机器的最大负载(完成时间)。

  • 算法思想(贪心策略)

    • List Scheduling:按顺序将每个任务分配给当前负载最小的机器。

    • Longest Processing Time First (LPT):先按任务处理时间从大到小排序,再用 List Scheduling 分配。

顶点覆盖问题

    • 问题描述:在无向图中找到一个最小的顶点集合,覆盖所有的边。

    • 算法思想(基于极大匹配)

      • 每次都挑选一条未覆盖的边(步骤3)。
      • 为了覆盖这条边,将它的两个端点(u和v)加入集合C(步骤4)。
      • 移除所有被u或v覆盖的边,减少未覆盖边(步骤5)。
      • 重复上述过程直到所有边都被覆盖。

旅行商问题(TSP,满足三角不等式)

  • 问题描述:在完全图中,找到一个经过所有顶点的最小权重哈密顿回路(满足三角不等式)。

  • 算法思想

    1. 用 Prim 或 Kruskal 算法构造最小生成树(MST)。

    2. 对 MST 进行前序遍历,得到访问顺序。

    3. 跳过重复顶点,直接按前序遍历顺序构造哈密顿回路。

    4. MST-PRIM(G, w, r)
      1  for each u ∈ G.V          # 初始化所有顶点的键值和父节点
      2      u.key = ∞             # 键值表示连接到当前树的最小边权
      3      u.π = NIL             # 父节点初始为空
      4  r.key = 0                 # 任选根节点 r,键值设为 0
      5  Q = G.V                   # 优先队列 Q 包含所有顶点
      6  while Q ≠ ∅
      7      u = Extract-Min(Q)    # 取出键值最小的顶点 u(首次为 r)
      8      for each v ∈ G.Adj[u] # 遍历 u 的邻接顶点 v
      9          if v ∈ Q and w(u,v) < v.key
      10             v.π = u        # 更新 v 的父节点为 u
      11             v.key = w(u,v) # 更新 v 的键值为边权 w(u,v)

相关文章:

  • 【PhysUnits】16.2 引入变量后的乘法实现(mul.rs)
  • arduino开发遇见的问题(求助!!)
  • springMVC-10验证及国际化
  • 深入理解 transforms.Normalize():PyTorch 图像预处理中的关键一步
  • 格恩朗液体涡轮流量计 精准测量 助力多元场景
  • 制作一款打飞机游戏67:更好的瞄准
  • Window Server 2019--11 虚拟专用网络
  • 【Java后端基础 005】ThreadLocal-线程数据共享和安全
  • vue3子组件获取并修改父组件的值
  • 企业私有化部署的平价革命:五步实现“低成本高可控”AI落地——破除百万投入迷思,中小企业也能玩转私有化大模型
  • 李沐《动手学深度学习》d2l安装教程
  • 在 Windows 系统上运行 Docker 容器中的 Ubuntu 镜像并显示 GUI
  • window查看SVN账号密码
  • 第四十六天打卡
  • 华为 “一底双长焦” 专利公布,引领移动影像新变革
  • vue中加载Cesium地图(天地图、高德地图)
  • 解决基于LangGraph框架的DeerFlow使用Qwen3不能正常被解析的问题
  • SOC-ESP32S3部分:31-ESP-LCD控制器库
  • TeamCity Agent 配置完整教程(配合 Docker Compose 快速部署)
  • Vite 双引擎架构 —— Esbuild 概念篇
  • 惠州做网站多少钱/南昌搜索引擎优化
  • 网站怎么能快速备案/网站关键词优化wang
  • 做相册哪个网站好/天津seo网络
  • 父亲节网页制作素材/网站seo收录工具
  • 网站视频做栏目一般一期多钱/东莞网站seo技术
  • 南昌网站开发/现在最好的免费的建站平台