绪论
-
五大特性
有穷性:在有限步之后结束。
确定性:每一条指令必须有确切的含义,不会产生二义性。
可行性:人们仅用笔和纸做有限次运算就能完成。
输入:有零个或多个输入。
输出:有一个或多个输出。 -
好算法的四大特性
正确性
健壮性
可靠性
高效性 -
渐进符号
渐进符号是数学和计算机科学中用来描述函数增长速率的符号,它们通常用于算法分析和复杂度理论。以下是三种常见的渐进符号:- O符号(大O符号):
- 表示上界(渐进上界)。
- Ω符号(大Omega符号):
- 表示下界(渐进下界)。
- Θ符号(大Theta符号):
- 表示上下界(紧渐进界)。称f(n)与g(n)同阶
这些符号帮助我们忽略掉低阶项和常数因子,专注于函数的主要增长趋势。例如,如果一个算法的时间复杂度是( n^2 + n ),我们通常说它是( O(n^2) ),因为它的主要增长趋势是二次方。
题目
NP问题,即非确定性多项式问题
下面关于NP问题说法正确的是(B )
A NP问题都是不可能解决的问题
B P类问题包含在NP类问题中
C NP完全问题是P类问题的子集
D NP类问题包含在P类问题中
任何可用计算机求解的问题所需的时间都与其 规模 有关。
一个算法就是一个有穷规则的集合,其中之规则规定了解决某一特殊类型问题的一系列运算,此外,算法还应具有以下五个重要特性:
确定性 ,有穷性 , 可行性, 0个或多个输入, 一个或多个输出。
算法的复杂性有_____________和___________之分,衡量一个算法好坏的标准是______________________。
时间复杂性 空间复杂性 时间复杂度高低
算法的复杂性是()的度量,是评价算法优劣的重要依据。
算法效率
递归算法
- 递归方程解的渐进阶求法(主方法)
T(n)=aT(n/b)+f(n)- 其中a≥1,b>1为常数,n为非负整数。
- T(n)表示算法的执行时间。
- 该算法将规模为n的原问题分解成a个子问题,每个子问题的大小为n/b,f(n)表示分解原问题和合并子问题解得到答案的时间。
- 计算(第二型易错):
-
基本概念
- 递归概述:
- 定义: 递归是一种编程技术,允许函数调用自身来解决问题。这在问题可以自然地被分解为相似的子问题时特别有用。
- 例子: 经典的递归例子包括计算阶乘、斐波那契数列等。
- 递归算法设计方法:
- 数学归纳法: 递归算法设计常常基于数学归纳法的原理。数学归纳法用于证明与自然数相关的命题,而递归算法设计则是利用类似的方法解决问题。
- 设计步骤: 包括识别问题的基本情况(递归出口),递归地解决问题的更小实例(递归体),并确保递归最终能够停止。
- 递归模型:
- 递归出口: 是指递归算法中停止递归的条件,通常是问题规模变得足够小,可以直接解决。
- 递归体: 描述了如何将问题分解为更小的子问题,并说明了如何结合这些子问题的解来得到原问题的解。
- 递归算法的执行过程:
- 系统栈: 递归调用是通过系统栈来实现的。每次递归调用都会将相关信息(如参数、局部变量和返回地址)压入栈中。
- 递归深度: 指的是递归调用的最大嵌套层数,它与问题规模有关。
- 递归算法的时间和空间复杂度分析:
- 时间复杂度: 描述了算法执行所需时间随输入规模增长的变化趋势。递归算法的时间复杂度可以通过递推式来求解,例如通过展开递归关系式来估计。
- 空间复杂度: 描述了算法执行过程中所需的存储空间量。对于递归算法,空间复杂度主要取决于递归深度,即系统栈中存储的调用帧数量。
好的,以下是对PPT中第7、8、9、11点的详细解释:
- 递归数据结构:
- 定义: 递归数据结构是一种数据组织方式,它允许数据结构的每个元素都可能包含对同一类型的子元素的引用。例如,二叉树中的每个节点都可能包含对左子树和右子树的引用。
- 应用: 递归算法非常适合操作递归数据结构,因为这些结构的自然分解方式与递归的分解问题方式相匹配。
- 例子: 单链表和二叉树是递归数据结构的典型例子。在单链表中,每个节点都包含对下一个节点的引用;在二叉树中,每个节点都包含对左右子树的引用。
- 基于归纳思想的递归算法设计:
- 归纳思想: 基于归纳思想的递归算法设计不是依赖于数据结构的递归特性,而是依赖于问题求解过程中的递归性质。
- 设计过程: 首先定义问题的基本情况,然后假设对于规模较小的问题已经有解,在此基础上推导出更大规模问题的解。
- 例子: 骨牌铺方格问题,通过归纳不同规模方格的铺放方案数,可以归纳出铺放方案总数的递推关系。
- 计算递推式:
- 直接展开法: 通过直接展开递推式来求解问题,通常用于简单的递推关系,可以直观地看到递推式的增长趋势。
- 递归树方法: 通过构建递归树来分析递推式的时间复杂度,每一层递归树代表递归调用的一个层次,将每层的复杂度求和得到总的时间复杂度。
- 主方法: 是一种更系统的方法,用于求解形如 ( T(n) = aT(n/b) + f(n) ) 的递推式,其中 ( a ) 是子问题的个数,( b ) 是子问题规模的缩放因子,( f(n) ) 是与问题规模相关的其他操作。
- 特定算法实例:
- 直接插入排序的递归实现: 将排序问题分解为已排序序列和未排序序列,递归地对未排序序列进行排序,并将元素插入到已排序序列中。
- 0/1背包问题的递归解法: 考虑每个物品是否放入背包,递归地求解放入和不放入情况下的最大价值,并选择价值最大的方案。
- 动态规划优化: 对于存在重复计算的递归问题,如0/1背包问题,可以使用动态规划来存储已解决的子问题结果,避免重复计算,提高效率。
- 基本计算器问题的递归解法: 对于包含加减运算和括号的表达式,可以递归地计算括号内的表达式,然后根据运算符将结果累加或相减。
分治法
- 分治算法的一般框架:
T divide-and-conquer(P) {//分治算法框架
if |P|≤n0 return adhoc(P);
将P分解为较小的子问题 P1,P2,…,Pk;
for(i=1;i<=k;i++) //循环处理k次
yi=divide-and-conquer(Pi); //求出子问题Pi的解
return merge(y1,y2,…,yk); //合并子问题的解
}
-
基本概念
- 分治法的基本思想:
- 分治法是一种算法设计范式,通过递归地将问题分解为更小的子问题来解决。这种方法通常用于可以被分解为相似子问题的大型问题。
- 子问题:(相对原问题)性质相同,规模较小,相对独立
- 分治法的三个主要步骤:
- 分解(Divide):将原问题分解成若干个规模较小的相同问题。
- 求解子问题(Conquer):独立地解决每个小规模的子问题。
- 合并(Combine):将子问题的解组合起来,形成原问题的解。
- 分治法的特性:
- 可缩性:问题可以被缩小到一个简单的基本情况,这个基本情况可以直接解决。
- 可分解性:问题可以被分解为多个小问题,这些小问题与原问题在结构上是相似的。(不用完全一致,相似就行)
- 可合并性:子问题的解可以方便地合并成原问题的解。
- 独立性:分解得到的子问题是相互独立的,不存在依赖关系。
- 分治算法的框架:
- 伪代码展示了分治算法的基本结构,包括递归终止条件、子问题的分解、子问题的递归求解以及解的合并。
- 分治算法的分析:
- 分析分治算法通常涉及到递推关系式的建立,这有助于理解算法的时间复杂度。例如,如果一个分治算法可以分解为a个子问题,每个子问题的规模是原问题的1/b,合并子问题解的时间为f(n),则总的时间复杂度可以表示为T(n) = aT(n/b) + f(n)。
-
应用
- 快速排序:
- 快速排序是一种高效的排序算法,使用分治法的思想。它通过选择一个元素作为“基准”,然后将数组分为两个子数组,一个包含小于基准的元素,另一个包含大于基准的元素。这个过程递归地应用于子数组,直到整个数组变为有序。
- 二路归并排序:
- 二路归并排序也是一种使用分治法的排序算法。它将数组分成两半,递归地对这两半进行排序,然后将排序好的两半合并成一个有序数组。归并过程是算法的关键部分,需要仔细设计以确保时间效率。
- 二分查找
- 最大连续子序列和
- 棋盘覆盖问题
- 循环日程安排问题
- 旅行商问题
- strassen矩阵*
- 减小子问题规模,减少乘法次数
ppt
题目
- 考过
1、二分搜索算法是利用(分治策略)实现的算法。
34.实现合并排序利用的算法是(分治策略 )。
实现大整数的乘法是利用的算法(分治策略 )。
17.实现棋盘覆盖算法利用的算法是(分治法 )。
29、使用分治法求解不需要满足的条件是(子问题必须是一样的 )。
不可以使用分治法求解的是(0/1背包问题 )。
快速排序算法的性能取决于 划分的对称性 。
- 可能考察
9.实现循环赛日程表利用的算法是(分治策略 )
27、Strassen矩阵乘法是利用(分治策略 )实现的算法。
适合动态规划法来求
回溯法
-
基本概念
- 回溯法的基本概念:
- 回溯法是一种通过试错来解决问题的算法策略,它尝试分步构造问题的解,如果某一步确定无法达到目标,则回退到上一步,尝试其他可能的解决方案。
- 解空间和解向量:
- 解空间是所有可能解构成的集合,通常可以表示为一棵树(解空间树),每个节点代表了解的一部分。
- 解向量是一个数组,用来记录解的组成部分,比如在0/1背包问题中,解向量的一个元素可以表示是否选择某个物品。
- 问题类型的分类:
- 求所有解类型:目标是找到所有满足约束条件的解,例如子集问题。
- 求最优解类型:除了满足约束条件外,还需要找到使目标函数最大化或最小化的解,例如背包问题。
- 深度优先搜索(DFS):
- 回溯法通常使用DFS来遍历解空间树,从根节点开始,尽可能深地搜索树的分支。
- 剪支技术:
- 剪支是一种提高搜索效率的方法,通过提前判断某些分支不可能产生有效解或不是最优解,从而避免无效搜索。
- 可行性剪支:剪去不满足约束条件的分支。
- 最优性剪支:使用限界函数剪去得不到最优解的分支。
- 回溯算法设计步骤:
- 明确问题模型和解空间结构。
- 确定结点的扩展规则和搜索顺序。
- 实现剪支函数以减少搜索空间。
- 时间复杂度分析:
- 通过分析解空间树的层数和每层结点数量,评估算法的时间复杂度。
- 例如,如果每层有m个结点,共有n层,则时间复杂度可以表示为O(m^n)。
- 子集树和排列树:
- 子集树:用于求解从n个元素中选择若干元素组成子集的问题,每个节点代表一个元素是否被选中。
- 2^n个子节点
- 排列树:用于求解排列问题,即如何将n个元素排列,每个节点代表一个元素在排列中的位置。
- 2!个子节点
-
子集树回溯算法框架
int x[n];//解向量,全局变量
void dfs(int i) {//子集树的递归框架
if(i>=n)//搜索到叶子结点
产生一个可能解;
else {
for (j=下界;j<=上界;j++){//用j枚举x[i]所有可能的选择
x[i]=j; //产生一个可能的解分量
… //其他操作
if (constraint(i) && bound(i))
dfs(i+1);//满足提交,继续下一层
}
}
}
- 排列树回溯算法框架
int x[n];//x为解向量
void dfs(int i) {//求解排列树的递归框架
if(i>=n)//搜索到叶子结点
产生一个可能解;
else {
for (j=i;j<=n;j++) {//用j枚举i所有可能的路径
… //x[i]选择x[j]的操作
swap(x[i],x[j]);
if (constraint(i) && bound(i))
dfs(i+1);//满足约束条件和限界函数
swap(x[i],x[j]);//回溯:恢复状态
… //回退到第i层结点的操作
}
}
}
题目
- 考过
回溯法解旅行售货员问题时的解空间树是( 排列树 )。
(剪枝函数)是回溯法中为避免无效搜索采取的策略
回溯法的效率不依赖于下列哪些因素( 确定解空间的时间 )
回溯算法和分支限界法的问题的解空间树不会是( 无序树 ).
回溯法在问题的解空间树中,按(D)策略,从根结点出发搜索解空间树。
A.广度优先
B. 活结点优先
C.扩展结点优先
D. 深度优先
回溯法的效率不依赖于以下哪一个因素?(C )
A. 产生x[k]的时间;
B. 满足显约束的x[k]值的个数;
C.问题的解空间的形式;
D.计算上界函数bound的时间;
E. 满足约束函数和上界函数约束的所有x[k]的个数。
F. 计算约束函数constraint的时间;
用回溯法解题的一个显著特征是在搜索过程中动态产生问题的解空间。在任何时刻,算法只保存从根结点到当前扩展结点的路径。如果解空间树中从根结点到叶结点的最长路径的长度为h(n),则回溯法所需的计算空间通常为(O(h(n)))。
在回溯法中,算法在任意时刻只跟踪从根结点到当前结点的路径,即当前路径上的所有结点。这个路径的长度就是算法所需的栈空间(或递归调用栈的深度)。对于深度为h(n) 的解空间树,所需的最大栈空间就是 h(n),这是因为在最坏情况下,算法可能需要递归地遍历整个路径,直到达到一个叶结点。因此,回溯法的空间复杂度与解空间树的高度成正比。
回溯法的算法框架按照问题的解空间一般分为(子集树)算法框架与(排列树)算法框架。
用回溯法解0/1背包问题时,该问题的**解空间结构为(子集树)**结构。
用回溯法解批处理作业调度问题时,该问题的**解空间结构为(排列树)**结构。
用回溯法解问题时,应明确定义问题的解空间,问题的解空间至少应包含___________。
一个(最优)解
以深度优先方式系统搜索问题解的算法称为_____________。
回溯法
- 可能考
回溯法是指(具有限界函数的深度优先生成法)。
分支限界法
- 基本概念
- 分支限界法概述:
- 分支限界法是一种在离散空间中搜索解决问题的方法,特别是用于求解组合优化问题。它通过系统地搜索解空间树来寻找问题的解。
- 解空间搜索方式:
- 深度优先搜索:沿着树的深度不断扩展,直到找到一个叶子结点,然后回溯。
- 广度优先搜索:从根结点开始,逐层扩展所有同层的结点,再扩展下一层。
- 存储结构:
- 栈:用于回溯法,按照后进先出的原则存储路径。
- 队列或优先队列:用于分支限界法,队列按照先进先出的原则存储结点,而优先队列根据优先级选择下一个扩展的结点。
- 结点存储特性:
- 在分支限界法中,每个结点只作为活结点一次,即一旦一个结点被扩展,它的所有子结点将被生成并存储,然后该结点将不再作为活结点。
- 限界函数:
- 上界限界函数(ub):用于最大化问题,确保子结点的上界值不大于父结点的上界值。
- 下界限界函数(lb):用于最小化问题,确保子结点的下界值不小于父结点的下界值。
- 活结点表的组织:
- 队列式分支限界法:活结点按照广度优先的顺序存储在队列中。
- 优先队列式分支限界法:活结点根据优先级存储在优先队列中,优先级最高的结点最先被扩展。
- 求最优解的解向量:
- 在搜索过程中,需要记录每个扩展结点的解向量,即从根结点到当前结点的路径。这可以通过保存当前结点的状态值和解向量来实现。
- 时间分析:
- 分析算法的时间复杂度,通常基于解空间树的层数和每层的结点个数。例如,如果每层有𝑚𝑖个结点,共有𝑛层,则算法的时间复杂度可以表示为
- 分析算法的时间复杂度,通常基于解空间树的层数和每层的结点个数。例如,如果每层有𝑚𝑖个结点,共有𝑛层,则算法的时间复杂度可以表示为
- 分支限界法概述:
- 应用
题目
- 考过
回溯算法和分支限界法的问题的解空间树不会是( 无序树 ).
分支限界法在问题的解空间树中,按(A)策略,从根结点出发搜索解空间树。
A.广度优先
B. 活结点优先
C.扩展结点优先
D. 深度优先
常见的两种分支限界法为(D)
A. 广度优先分支限界法与深度优先分支限界法;
B. 队列式(FIFO)分支限界法与堆栈式分支限界法;
C. 排列树法与子集树法;
D. 队列式(FIFO)分支限界法与优先队列式分支限界法;
- 可能考
最大效益优先是( 分支限界法 )的一搜索方式。
分支限界法解最大团问题时,活结点表的组织形式是( 最大堆 )。
分支限界法解旅行售货员问题时,活结点表的组织形式是( 最小堆 )
优先队列式分支限界法选取扩展结点的原则是( 结点的优先级 )
在对问题的解空间树进行搜索的方法中,一个活结点最多有一次机会成为活结点的是( 分支限界法 ).
从活结点表中选择下一个扩展结点的不同方式将导致不同的分支限界法,以下除( 栈式分支限界法 )之外都是最常见的方式.
(1)队列式(FIFO)分支限界法:按照队列先进先出(FIFO)原则选取下一个节点为扩展节点。
(2)优先队列式分支限界法:按照优先队列中规定的优先级选取优先级最高的节点成为当前扩展节点。
动态规划法
-
基本概念
-
动态规划的基本概念:理解动态规划的定义,它是一种将复杂问题分解为重叠子问题并存储这些子问题的解以避免重复计算的方法。适用于解决具有以下特点的问题:
- 多阶段决策问题:问题可以分解为多个决策阶段。
- 重叠子问题:在递归算法中,很多子问题是重复计算的。
- 最优子结构:问题的最优解包含子问题的最优解。
-
性质
- 最优子结构性质:一个问题的最优解由其子问题的最优解构成。
- 无后效性:一旦某个阶段的状态确定,该状态以后的过程与之前的状态无关。
- 重叠子问题性质:在递归过程中,很多子问题是重复出现的。
-
基本步骤
- 确定状态:将问题求解中各个阶段所处的各种情况用不同的状态表示出来。
- 确定状态转移方程:描述求解中各个阶段的状态转移和指标函数的关系。
- 确定初始条件和边界情况:状态转移方程通常是一个递推式,初始条件通常指定递推的起点,在递推中需要考虑一些特殊情况,称为边界情况。
- 确定计算顺序:也就是指定求状态转移方程的顺序,是顺序求解还是逆序求解。
- 消除冗余:如采用滚动数组进一步提高时空性能。
-
求解过程
动态规划求解步骤:掌握如何确定状态、状态转移方程、初始条件和边界情况,以及计算顺序。- 识别子问题:将问题分解为若干个规模较小的子问题。
- 确定状态:定义问题的阶段以及每个阶段的状态。
- 状态转移方程:找出状态之间的关系,即当前状态是如何由前一状态推导出来的。
- 确定初始状态和边界条件:设置问题的初始状态,以及在求解过程中需要考虑的边界条件。
- 确定计算顺序:决定计算状态的顺序,可以是自顶向下(备忘录法)或自底向上(表格法)。
- 构造最优解:根据DP表,构造问题的最优解。
- 优化:考虑是否存在状态压缩或空间优化的可能性,以减少时间和空间复杂度。
-
动态规划数组(DP数组):理解DP数组的作用,以及如何使用它来存储子问题的解。
-
滚动数组技术:了解如何通过滚动数组减少空间复杂度。
-
-
应用
斐波那契数列:改进递归算法,使用动态规划避免重复计算。
最大连续子序列和:使用动态规划求解最大子序列和问题。
最长递增子序列:求解序列中最长递增子序列的长度。
三角形最小路径:在给定的三角形中找到从顶部到底部的最小路径和。
最长公共子序列:找到两个字符串的最长公共子序列。
编辑距离:计算将一个字符串转换为另一个字符串的最少编辑操作次数。
0/1背包问题:在不超过背包容量的前提下,选择物品以最大化价值。
完全背包问题:每种物品可以无限取用,求最大价值。
多重背包问题:每种物品有数量限制,求最大价值。
扔鸡蛋问题:确定楼层的最少操作次数问题。
资源分配问题:合理分配资源以最大化总收益。
旅行商问题:寻找访问所有城市一次并返回起点的最短路径。
最少士兵数问题:在树结构的城市中放置最少数量的士兵以观察所有边缘。
题目
- 考过
下列不是动态规划算法基本步骤的是( 构造最优解 )
下列是动态规划算法基本要素的是(子问题重叠性质 )。
下列算法中通常以自底向上的方式求解最优解的是(动态规划法 )
备忘录方法是哪一种算法的变形。( 动态规划法 )
最长公共子序列算法利用的算法是( 动态规划法 )。
(最优子结构性质)是贪心算法与动态规划算法的共同点。
贪心算法与动态规划算法的主要区别是( 贪心选择性质 )。
应用Johnson法则的流水作业调度采用的算法是(D)
A. 贪心算法
B. 分支限界法
C.分治法
D. 动态规划算法
动态规划算法的基本要素为(C)
A. 最优子结构性质与贪心选择性质
B.重叠子问题性质与贪心选择性质
C.最优子结构性质与重叠子问题性质
D. 预排序与递归调用
某一问题可用动态规划算法求解的显著特征是_________________________。
该问题具有最优子结构性质
动态规划算法的基本思想是将待求解问题分解成若干____________,先求解___________,然后从这些____________的解得到原问题的解。
子问题 子问题 子问题
动态规划算法的两个基本要素是___________和___________。
最优子结构性质,重叠子问题性质
- 可能考
矩阵连乘问题的算法可由(动态规划算法B)设计实现。
实现最大子段和利用的算法是( 动态规划法 )。
01背包问题
贪心法
-
基本概念
-
贪心法概述:
- 贪心法是一种算法设计策略,用于求解优化问题。
- 贪心法的基本思想是每一步都做出在当前状态下最好或最优的选择,从而希望导致结果是全局最好或最优的。
-
贪心法的性质:
- 最优子结构性质:如果一个问题的最优解包含的子问题的解也是最优的,那么这个问题具有最优子结构性质。
- 贪心选择性质:整体最优解可以通过一系列局部最优选择来得到。
-
贪心法求解过程:
- 建立数学模型描述问题。
- 将问题分解为子问题。
- 对每个子问题求解局部最优解。
- 将局部最优解合并为原问题的全局最优解。
-
最小代价生成树
MST性质(最小生成树性质)- Kruskal算法(避圈法):依次添加最小的边,但是要避免成环
- Prim算法:随变从一点开始,依次添加最小的边连接的点到整体(也要避免成环)
-
-
应用
区间问题:
活动安排问题:如何在有限资源的情况下,选择最大数量的不相交活动。
贪心策略:总是选择结束时间最早的活动。
背包问题:
选择物品装入背包,使得价值最大,但不超过背包容量。
贪心策略:选择单位重量价值最大的物品。
田忌赛马问题:
如何安排马匹比赛以获得最大收益。
零钱兑换问题:
使用最少数量的硬币来兑换特定金额。
贪心策略:优先使用面额大的硬币。
哈夫曼编码:
根据字符出现的频率来构造最优的不等长编码方案。
拟阵:
一种数学结构,包含一个有限集合以及满足特定条件的子集族。
拟阵在任务调度、组合优化问题中有应用。
任务调度问题:
如何安排任务以最小化惩罚或最大化收益。
超市问题:
如何安排商品销售以最大化利润。
题目
- 考过
能解决的问题:单源最短路径问题,最小花费生成树问题,背包问题,活动安排问题;
不能解决的问题(最优解):N皇后问题,0/1背包问题
是贪心算法的基本要素的是(贪心选择性质和最优子结构性质)。
(最优子结构性质)是贪心算法与动态规划算法的共同点。
贪心算法与动态规划算法的主要区别是( 贪心选择性质 )。
能采用贪心算法求最优解的问题,一般具有的重要性质为:(A)
A. 最优子结构性质与贪心选择性质
B.重叠子问题性质与贪心选择性质
C.最优子结构性质与重叠子问题性质
D. 预排序与递归调用
贪心算法总是做出在当前看来( )的选择。也就是说贪心算法并不从整体最优考虑,它所做出的选择只是在某种意义上的()。
最好 局部最优选择
许多可以用贪心算法求解的问题一般具有2个重要的性质:( )性质和( ) 性质。
最优子结构性质 贪心选择性质
某个问题的最优解包含着其子问题的最优解。这种性质称为(最优子结构性质)。
- 可能考
所谓最优子结构性质是指(问题的最优解包含了其子问题的最优解)。
所谓贪心选择性质是指(所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到)。
每次两两合并权值最小的两个节点