991算法部分终极复习

1、比较分治法和动态规划的异同点

1. 主要共同点:
二者都是将原问题分解成若干个规模较小的子问题(小到很容易解决),然后将子问题的解合并,形成原问题的解。

2. 主要区别:
① 分治法将分解后的子问题看成相互独立的。
② 动态规划将分解后的子问题理解为相互间有联系,有重叠部分。

     动态规划划分的子问题是有优先的。

例如:问题p划分为子问题p1,p2,p3,... ,pn

p1为边界,解决p2必须先解决p1,解决p3必须先解决p2,依次类推,直到解决pn,一般解决子问题pn即能解决p。

3. 分治法与动态规划实现方法:
① 分治法通常利用递归求解。(例:归并排序,快速排序,一般用树结构)
② 动态规划通常利用迭代法自底向上求解。(例:最短路径,最优二叉搜索树

分治法P16 动态规划P204

分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后再合并这些子问题的解 来建立原问题的解。

分治模式在每层递归时都有三个步骤:

  1. 分解原问题为若干子问题,这些子问题是原问题的规模较小的实例。
  2. 解决这些子问题,递归地求解各子问题。(若子问题的规模足够小则直接求解)
  3. 合并这些子问题的解成为原问题的解。

分治模式举例:归并排序算法:分解+解决+合并。

①分解待排序的n个元素的序列,成为各具n/2个元素的两个子序列。

②解决:使用归并排序递归的排序两个子序列。

③合并两个已排序的子序列以产生最终答案。【当待排序的序列长度为1时,因为长度为1的每个序列都已排好序,此时递归“开始回升”。】

归并排序算法的关键操作是两个已排序序列的合并。通过调用一个辅助过程Merge(A,p,q,r)来合并两个已排好序的子数组A[p,q]和A[q+1,r]。过程Merge需要时间Θ(n)——每次只比较顶上的两个元素,每个基本步骤需要常量时间,最多执行n个基本步骤,所以合并时间Θ(n)。

分治方法将问题划分为互不相交的子问题,递归地求解子问题,再将它们的解组合起来,求出原问题的解。与分治法相反,

动态规划(dynamic programming)应用于子问题重叠的情况,即不同的子问题具有公共的子子问题(子问题的求解是递归进行的,将其划分为更小的子子问题),通过组合子问题来求解原问题。

动态规划算法对每个子子问题只求解一次,将其解保存在一个表格中,从而无需每次求解一个子子问题都要重新计算。动态规划通常用来求解最优化问题。注意:最优化问题可能有多个解都达到最优值。

设计一个动态规划算法的步骤:

  1. 刻画一个最优解的结构特征;
  2. 递归地定义最优解的值;
  3. 计算最优解的值,通常采用自底向上的方法;
  4. 利用计算出的信息构造一个最优解(按照要求,可有可无);

适合用动态规划方法求解的问题应该具备的两个关键特征:最优子结构+子问题重叠

性质一、最优子结构:一个问题的最优解包含其子问题的最优解【原理:使用动态规划方法时,我们用子问题的最优解来构造原问题的最优解】

性质二、子问题重叠:递归算法反复求解相同的子问题【区别于分治法:在每次递归都生成全新的子问题

动态规划方法举例:

最优钢条切割】如何将长钢条切割成短钢条,使得总价值最高。

【矩阵链乘法】如何用最少的标量乘法完成一个矩阵链相乘的算法。

最长公共子序列】找到两个序列的最长公共子序列。

最优二叉搜索树】在已知关键字分布的前提下,如何构造一课最优二叉搜索树。


贪心算法

P237

对于许多最优化问题,使用动态规划算法来求最优解有些杀鸡用牛刀了,可以使用更简单高效的贪心算法。

贪心算法:在每一步都作出当时看来最好的选择,寄希望这样的选择能导致全局最优解。(算法得到的是在某种意义上的局部最优解。)贪心算法并不能保证得到最优解,但对很多问题确实可以得到最优解,关键是贪心策略的选择。

贪心算法一般按照如下步骤进行:

  1. 建立数学模型来描述问题
  2. 把求解的问题分成若干个子问题
  3. 对每个子问题求解,得到子问题的局部最优解
  4. 把子问题的解局部最优解合成原来问题的一个解

贪心算法例子:

最小生成树(Prim算法、Kruskal算法)

单源最短路径的Dijstra算法

集合覆盖问题的贪心算法


2、递归和非递归的优缺点

递归:

优点缺点
可读性好,代码简洁所需空间大,可能会出现子问题的重复计算,递归太深时容易栈溢出

非递归(迭代):

优点缺点
效率高,无额外空间开销代码不如递归简洁,编写复杂问题时不容易理解

   通俗地说,递归就是将问题层层细化、分解为多个小问题,然后一一解决。在很多情况下,只要有数学公式的支持,递归算法通常很容易解决问题。


大数乘法

所谓大数相乘(Multiplication algorithm),就是指数字比较大,相乘的结果超出了基本类型的表示范围,所以这样的数不能够直接做乘法运算。

eg求 1234567891011121314151617181920 * 2019181716151413121110987654321 的乘积结果。

目前大数乘法算法主要有以下几种思路:

模拟小学乘法:最简单的乘法竖式手算的累加型(思路虽然很简单,但是实现起来却很麻烦)
分治乘法:最简单的是Karatsuba乘法(递归乘法,把输入拆分成 2 部分)
快速傅里叶变换FFT:时间复杂度O(N lgN lglgN)
中国剩余定理:把每个数分解到一些互素的模上,然后每个同余方程对应乘

【算法】大数乘法问题及其高效算法_Mlib的博客-CSDN博客


如何在有向图中计算强连通分量?

有向图的强连通分量 :在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点“强连通”。如果有向图G的每两个顶点都强连通,称G是一个强连通图有向图的极大强连通子图,称为强连通分量。

有向图中的强连通性是一种顶点之间平等关系,有着以下性质:

自反性: 任意顶点和自己都是强连通的
对称性:如果v和w是强连通的,那么w和v也是强连通的
传递性:如果v和w是强连通的且如果w和x也是强连通的,那么v和x也是强连通的

在这里插入图片描述 
如上图可以分为5个强连通分量。 一个含有V个顶点的有向图可能有1~V个强连通分量;一个强连通图只含一个强连通分量;而一个有向无环图中含有V个强连通分量。

【求强连通分量】

  1. Kosaraju算法:O(N+M)
  2. Tarjan算法:O(N+M)
  3. Gabow算法

AVL平衡二叉查找树的建立、删除操作,证明删除一个结点的时间复杂度。

增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。


公司盈利问题,计算极大子组,分三种方法:暴力算法、分治法、动态规划


时间复杂度的符号表示(渐进符号)

算法导论:时间复杂度+渐进符号_zwy2022的博客-CSDN博客


选择排序,插入排序,快速排序,归并排序,堆排序

在这里插入图片描述

In-place

假如问题规模是n,在解决问题过程中,只开辟了常数量的空间,与问题规模n无关,这是原址操作,就是In-place。

Out-place

如果开辟的辅助空间与问题规模n有关,则是out-place。
假设你把排序时把数组中的数按顺序放入了一个新的数组,我就开了一个n规模大小的数组,这个就与问题规模n有关。

关键字记忆法:

冒泡排序【从后往前,两两比较,小的浮到最前面】

选择排序【每次从待排序序列中,选择最小/最大,放到已排序列的尾部】

插入排序【每次都取待排序列的,第一个元素,往前插到已排序列的合适位置】

希尔排序【优先比较距离较远的元素,按一定增量分组,不断缩小增量】

归并排序【分治法,自下而上递归】【将两个有序表合并成一个有序表,称为2-路归并】

快速排序【每次取一个基准/枢轴进行分区,小—基准—大。分治法,一串分成两串……】

【算法实现:填坑,每次先把基准的位置拿出来当作坑。两个指针L和R,R先左移,适当元素拿去填坑,然后坑位转移。L右移,适当元素拿去填坑,然后坑位转移……当L=R时停止移动,共同指向的坑用来填基准】4分钟动画-秒懂快速排序

堆排序【无序序列先拆分成单个单个的元素,按顺序排成一棵完全二叉树。从倒数第一个非叶子结点开始,从后往前进行调整<堆的有序化>】   

【堆的插入:在数组末尾插,再自下而上进行堆有序化

【堆的删除:删的是堆顶元素,但并不是直接删先。交换根结点与最后一个叶子结点的位置,然后再删除最后一个结点,再自上而下进行堆有序化

选择排序时间复杂度稳定:O(n^{2})

归并排序时间复杂度稳定:O(nlog n)

堆排序时间复杂度稳定:O(nlog n)


NPC问题

算法4类问题:P问题、NP问题、NP完全问题、NP难问题_zwy2022的博客-CSDN博客


堆的向下调整算法、堆的向上调整算法、堆的基本功能实现

堆的向下调整算法、堆的向上调整算法、堆的基本功能实现_zwy2022的博客-CSDN博客


字符串模式匹配

数据结构 第四章 字符串_zwy2022的博客-CSDN博客


什么是循环队列

顺序队列臆造成一个环状的空间,即把存储队列元素的表从逻辑上视为一个环,称为循环队列。

  • 初始时<队空>:front=rear
  • 出队入队时,指针都按顺时针方向进1。出队--队首指针进1:front=(front+1)%Size。入队--队尾指针进1:rear=(rear+1)%Size
  • 队列中元素个数:(rear -front +Size)%Size
  • 为了区分队空还是队满,有三种处理方式。1)牺牲一个单元来区分。队满条件:(rear +1)%Size=front。队空条件:仍为front=rear。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值