| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 算法设计与分析知识点整理 -> 正文阅读 |
|
[数据结构与算法]算法设计与分析知识点整理 |
前言本文是针对算法设计与分析这门课的知识点整理,内容多来源于教科书以及我看到的一些优秀博文,其中我最推崇是《labuladong的算法小抄》,它的内容让我眼前一亮,不同于教科书的死板套路,它从不一样的角度去解读学习算法,语言通俗易懂,让我受益匪浅。 我特别喜欢其中说的一句话
一、算法的基本概念算法是求解问题的一系列计算步骤,用来将输入数据转换为输出结果。 1.算法的基本特征
2.算法设计需要满足的目标
3.算法和程序的区别一、形式不同 1、算法:算法在描述上一般使用半形式化的语言。 2、程序:程序是用形式化的计算机语言描述的。 二、性质不同 1、算法:算法是解决问题的步骤。 2、程序:程序是算法的代码实现。 三、特点不同 1、算法:算法要依靠程序来完成功能。 2、程序:程序需要算法作为灵魂。 二、时间复杂度计算1.大O表示法"大O表示法"表示程序的执行时间或占用空间随数据规模的增长趋势。大O表示法就是将代码的所有步骤转换为关于数据规模n的公式项,然后排除不会对问题的整体复杂度产生较大影响的低阶系数项和常数项。
2.最坏和平均情况指算法在所有输入I下的所执行基本语句的最多执行次数和平均次数 3.根据递归方程求解时间复杂度3.1 根据递归树求解①画递归图 ②相加化简得时间复杂度 3.2 根据主方法求解主定理:a ≥ 1 和 b > 1,是常数,f ( n )是一个函数,T(n)是定义在非负整数上的递归式:
三、六大算法
1.分治法1.1 算法思路先「分」后「治」,先按照运算符将原问题拆解成多个子问题,然后通过子问题的结果来合成原问题的结果。 1.2 适用范围
1.3 基本步骤①分解出若干个子问题 ②求解子问题 ③子问题合并 2.回溯法(DFS)2.1 算法思路解决一个回溯问题,实际上就是一个决策树的遍历过程。(其实就是穷举,如果配合着剪枝技巧就是聪明的穷举) 注:DFS使用的数据结构是栈,往往利用递归来解决(递归调用利用的就是系统栈) 2.2 算法步骤①针对给定的问题确定解空间 ②确定结点的拓展搜索规则 ③以深度优先搜索(DFS)的方式搜索解空间树,并在搜索过程中可以采用剪枝函数来避免无效搜索。 2.3 算法框架
2.4 算法技巧①剪枝函数——聪明的穷举 对于一些明显不符合题意的分支进行剪枝,避免无效穷举。 ②数组交换 这个用于解空间为全排列树的情况,而且保存路径的方式为数组,此时可以对数组数据进行交换来保证排列中的每个元素不同。 3.分枝限界法(BFS)虽然不喜欢官方的定义,但是为了更好理解这个名字,还是要了解以下概念: 分枝——使用广度优先的策略 限界——使用限界函数计算函数值(可以理解为权重)来决定遍历顺序 3.1 算法思路和回溯法一样都是穷举决策树,不过分支限界法使用**广度优先遍历(BFS) **的方式穷举。 这种穷举方式使分支限界法有以下特点: ①BFS 找到的路径一定是最短的,但代价就是空间复杂度可能比 DFS 大很多 ②适用于找到某种意义下的最优解(其实也可以选择遍历决策树找到找到符合条件的解,但是这样一来时间复杂度和DFS一样,但是空间复杂度却高了很多,得不偿失) ③在找最优解中,BFS往往时间复杂度更低,但空间复杂度更高(不需要像DFS那样遍历所有节点,但代价就是需要额外空间来存储至少一层的结点) ④往往用队列/优先队列的数据结构 3.2 算法框架
3.3 算法技巧①优先队列优先弹出更优的结点,这样可以更快找到最优解。 ②双向 BFS 优化传统的 BFS 框架就是从起点开始向四周扩散,遇到终点时停止;而双向 BFS 则是从起点和终点同时开始扩散,当两边有交集的时候停止。 在算法实现上还有技巧,每次扩散结点时选择较小一端(较小的队列),如果我们每次都选择一个较小的集合进行扩散,那么占用的空间增长速度就会慢一些,效率就会高一些。 不过,双向 BFS 也有局限,因为你必须知道终点在哪里。 4.贪心法4.1 算法思路并不从全局最优上考虑,而是每次都做当前的局部最优选择。
4.2 适用范围使用贪心算法需要满足以下性质: ① 贪心选择性质 该性质是说所求问题的整体最优解可以通过一系列局部最优的选择来达到。而要确定一个问题是否具有这种性质,必须证明每一步所做的贪心选择最终会导致全局最优解。 ②最优子结构性质 当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。这种性质是问题可用动态规划或贪心解决的重要特征。 4.3 算法求解过程①建立数学模型描述问题 ②把求解的问题分成若干个子问题 ③把每个子问题求解,得到子问题的局部最优解 ④把子问题的局部最优解合成原来解问题的一个解 4.4 算法证明其实很多时候我们能凭借生活经验和直觉判断出这就是个贪心问题,但是解题是最难的便是证明它。 我们可以去证明问题的贪心选择性质和最优子结构性质来证明贪心算法的正确性。 最优子结构的证明思路: a) 定义子问题空间,做出一个选择从而产生一个或多个子问题。子问题空间的定义结合需要求解的目标和选择后子问题的描述刻画来考虑。 贪心选择性质的证明思路: 贪心的本质是局部最优解能产生全局最优解,即产生两个子问题S1和S2时,可以直接解决子问题S1(在子问题S1中,使用贪心策略选择a作为局部最优解)然后对子问题S2进行分解,最终可以合并为全局最优解。 Exchange Argument方法定义通过非贪心策略的选择可以得到的一个最优解A,将最优解中的元素和当前贪心策略会选择的元素逐个交换后得到的解A’并不比 5.动态规划5.1 算法思路把多阶段过程转化为一系列单阶段问题,并利用各阶段之间的关系逐个求解。 5.2 从穷举角度看动态规划以下摘自《labuladong的算法小抄》
5.3 适用范围①最优化原理(最优子结构性质) 问题的最优解所包含的子问题的解也是最优的 ②无后效性 某阶段的状态一旦确定,就不受这个状态以后决策的影响。 ③有重叠子问题 子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。 5.4 算法框架
5.5 三种常用思路(解题步骤)下述思路往往是递进的关系 ①暴力递归暴力递归可不简单,要想暴力递归出解法,首先得知道状态转移方程
如何列出正确的状态转移方程? 1、确定 base case 2、确定「状态」,也就是原问题和子问题中会变化的变量 3、确定「选择」,也就是导致「状态」产生变化的行为 4、明确 明确上述几点后,我们就能根据其写出状态转移方程,根据状态转移方程我们也就能很快写出对应的递归代码。 ②带备忘录的递归由于重叠子问题的存在,暴力递归的效率往往很低,原因在于会重复对某些状态进行递归。因此我们自然而然就想到可以通过备忘录的形式把每个状态的值记录下来,等下次再用到的时候就不用大费周章再去递归一遍,而是直接拿。 很显然「备忘录」大大减小了子问题数目,完全消除了子问题的冗余,做到了“聪明的穷举”。 ③dp 数组的迭代解法dp 数组的迭代解法和递归的思路很像,也是需要一个dp数组来记录状态,不过递归解法往往是一个自上而下的过程,而它是自下而上层层迭代的过程——由先前的状态迭代往后得出后面的状态。 这种自下而上的思路往往不符合人的惯性思维,解题时往往要搞清楚状态之间的先后关系,必须先遍历初始的状态,再根据状态慢慢演变得出后续的状态,在得到答案之前,它需要遍历所有状态。 当然这种解法往往存在一种技巧——状态压缩(或者叫做滚动数组),如果计算状态 总结递归写法往往更符合人的思考方式,可以更容易写出答案,自上而下的解法可以只对需要的状态求解,在一定程度上提高效率。 dp数组的迭代解法是一种自下而上的解题思路,需要明确状态的先后关系,往往不太符合人的思考方式,得到答案之前需要遍历所有状态。不过它可以用状态压缩/滚动数组的技巧来降低空间复杂度。 在解动态规划问题时,我们可以先从暴力递归入手,逐步去优化写出最终的答案,一般写到带备忘录的递归即可。 6.概率算法6.1 数值概率算法常用于解决数值计算的问题。该算法往往只能得到问题的近似解,并且该计算解的精度一般随着计算时间的增加而不断提高。 6.2 蒙特卡罗算法蒙特卡罗算法用于求问题的准确解。蒙特卡洛算法1945年由冯诺依曼行核武模拟提出的。它是以概率和统计的理论与方法为基础的一种数值计算方法,它是双重近似:一是用概率模型模拟近似的数值计算,二是用伪随机数模拟真正的随机变量的样本。 当所求解问题是某种随机事件出现的概率,或者是某个随机变量的期望值时,通过某种“实验”的方法,以这种事件出现的频率估计这一随机事件的概率,或者得到这个随机变量的某些数字特征,并将其作为问题的解。 蒙特卡罗算法能求得问题的一个解,但这个解未必是正确的。求得正确解的概率依赖于算法所用的时间。算法所用的时间越多,得到正确解的概率就越高。蒙特卡罗算法的主要缺点就在于此。一般情况下,无法有效判断得到的解是否肯定正确。 示例问题:根据伪随机数求π 6.3 拉斯维加斯算法拉斯维加斯算法不会得到不正确的解,一旦用拉斯维加斯算法找到一个解,那么这个解肯定是正确的。但是有时候用拉斯维加斯算法可能找不到解。与蒙特卡罗算法类似。拉斯维加斯算法得到正确解的概率随着它用的计算时间的增加而提高。对于所求解问题的任一实例,用同一拉斯维加斯算法反复对该实例求解足够多次,可使求解失效的概率任意小。 示例问题:求解n皇后 6.4 舍德伍算法舍伍德算法总能求得问题的一个解,且所求得的解总是正确的。当一个确定性算法在最坏情况下的计算复杂性与其在平均情况下的计算复杂性有较大差别时,可以在这个确定算法中引入随机性将它改造成一个舍伍德算法,消除或减少问题的好坏实例间的这种差别。舍伍德算法精髓不是避免算法的最坏情况行为,而是设法消除这种最坏行为与特定实例之间的关联性。 四、计算复杂性理论1.图灵机模型图灵机是一种数学计算模型,它定义了一个抽象机器,该抽象机器根据规则表来操纵带子上的符号。尽管该模型很简单,但是在任何给定计算机算法的情况下,都可以构建出模拟该算法逻辑的图灵机。 简单点说,图灵机就是一个模拟算法运行的抽象机器。它是这样定义的:
①确定图灵机在确定性图灵机(DTM)中,其控制规则规定了在任何给定情况下最多只能执行一个动作。 确定性图灵机具有转换功能,对于磁带头下的给定状态和符号,该转换功能指定了三件事: 要写入磁带的符号,头部应移动的方向(向左,向右或都不向),以及有限控制的后续状态。 例如,状态3的磁带上的X可能会使DTM在磁带上写Y,将磁头向右移动一个位置,然后切换到状态5。 ①非确定图灵机在理论计算机科学中,非确定性图灵机(NTM)是一种理论计算模型,其控制规则在某些给定情况下指定了多个可能的动作。 也就是说,NTM的下一个状态不是完全由其动作和它所看到的当前符号决定的(不同于确定性图灵机)。 3.P、NP、NPC类问题P问题:有多项式时间算法,算得很快的问题。 NP问题:算起来不确定快不快的问题,但是我们能在多项式时间内验证得出一个正确解的问题 NP-complete问题:存在这样一个NP问题,所有的NP问题都可以约化成它。换句话说,只要解决了这个问题,那么所有的NP问题都解决了。 NP-hard问题:比NP问题都要难的问题。 参考博文: 对上述框架思维的总结和概述 :: labuladong的算法小抄 (gitee.io) 用递归树方法求解递归式_疙瘩村村书记-CSDN博客_递归树求解递归方程 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 18:22:27- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |