算法概述——四大算法总结

1、什么是算法

什么是算法? 简而言之就是解决一个问题具体方法或者说过程,也就是能根据实际情况输入对应条件,在有限的时间内获得所要求的结果。因为计算机的运算资源和存储容器是有限的,为了保证程序的执行效率,我们需要再面对具体问题时采用合适的算法去处理问题,而解决同一个问题的不同的算法的效率可能会相差非常大,算法效率的差距影响有时甚至比计算机配置的差距还要更大,所以面对问题时一个正确的合适的算法至关重要!算法和数据结构构成可运行程序,算法是程序的灵魂!

1.1、算法的特征

可行性,算法中执行的任何计算步骤都可以在有限时间里完成;
确定性,算法的每一步都要有确切的意义,不能有二义性;
有穷性,算法的有穷性是指算法必须在执行有限个步骤后终止,不能无限循环;
输 入,可根据实际情况输入或设定对应条件,以刻画运算对象的初始情况;
输 出,输出根据输入数据运算后的结果,没有输出的算法是没有意义的!

1.2、算法的评价

通常一个好算法应该达到如下目标:
正确性,算法应该正确的解决问题。
可读性,算法应该具有较好的可读性,让人们理解算法的作用。
健壮性,异常情况的容错性,比如输入非法数据时,算法也可以做出适当的反应,而不会崩溃或者产生莫名其妙的结果。

1.3、算法的复杂度

算法复杂度是指算法在变为可执行程序后所耗费的时间资源和内存。
时间复杂度: 评估程序所需要的时间。
空间复杂度: 评估程序所需要的储存空间。
注:一般都优先考虑时间复杂度。

2、四大经典算法

2.1、分治算法

2.1.1、是什么

分治算法是什么?按字面理解就是分而治之,主要分为两部分,首先就是将原本规模较大的问题不断拆分,缩小子问题规模,达到最优子结构。然后合并,在合并过程中,应为子问题足够小,容易计算,再不断合并子问题答案,最终求出问题解,这就是所谓的分治法。这个技巧是很多高效算法的基础,如排序算法,递归算法等,这些会在后续文章中结合实例具体讲解。

2.1.2、为什么

为什么要用分治法?因为任何一段函数在程序运行过程中解决问题所需的资源都与其规模有关。问题的规模越小,越容易直接求解,解题所需的计算资源也越少。要想直接解决一个规模较大的问题,有时是相当困难的,但是将问题拆分后,随着问题的规模不断缩小,最终的子问题很容易直接求出其解,这样就能极大的简化代码的复杂度和提高运行速度减少资源消耗。

2.1.3、怎么用

分治法怎么用? 遇到问题时使用分治法在每一层递归上都有三个步骤:
1)分解: 分析问题,将原问题分解为若干个与原问题形式相同的规模更小且容易解决的子问题;
2)解决: 若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
3)合并: 将各个子问题的解合并为原问题的解。

2.1.4、总结

分治法面向问题具有以下几个特征,在同时符合以下特征时就可以使用分治法去解决问题:
1) 该问题可以分解为若干个规模较小的容易解决的相同问题,即该问题具有最优子结构性质;
2) 利用该问题分解出的子问题的解可以合并为该问题的解;
3) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。

2.2、回溯算法

2.2.1、是什么

回溯算法又称为试探法,是一种试错思想,将问题的候选解按某种顺序逐一进行枚举和检验。当发现当前候选解不可能是正确的解时,就选择下一个候选解。如果当前候选解除了不满足问题规模要求外能够满足所有其他要求时,则继续扩大当前候选解的规模,并继续试探。如果当前候选解满足包括问题规模在内的所有要求时,该候选解就是问题的一个解。比如常见的迷宫路线选择问题,通过选择不同的分岔路线,一个个去尝试寻找出口,如果遇到死胡同则返回到之前非分岔点重新选择另一条路线,直到最终走出迷宫,这种走不通就退回再走的思想为回溯法思想,而满足回溯条件的某个状态的点称为“回溯点”。

2.2.2、为什么

回溯算法相对于暴力搜索而言,会对每一步探测高的情况进行评估,如果当前情况已经无法满足要求,,那么就没有必要继续进行下去,即他可以帮助我们避免走很多的弯路,提高搜索效率!

2.2.3、怎么用

1) 分析问题,定义问题的解空间;
2) 确定易于搜索的解空间结构;
3) 当前情况下,遍历所有可能出现的情况并进行下一步的尝试;
4) 判断当前情况是否成立,如果非法则进行剪枝,就立即返回即取消前一步进行的尝试;
5) 当前情况是否已经满足递归结束条件,如果是就将当前结果保存起来并返回;

2.2.4、总结

回溯算法就是以深度优先方式搜索问题的解空间,并在搜索过程中用剪枝函数避免无效搜索,从而提高代码效率!

2.3、贪心算法

2.3.1、是什么

贪心算法也被称为贪婪算法,它在求解问题时总想用在当前看来是最好方法来实现。这种算法思想不从整体最优上考虑问题,仅仅是在某种意义上的局部最优求解。虽然贪心算法并不能得到所有问题的整体最优解,但是面对范围相当广泛的许多问题时,能产生整体最优解或者是整体最优解的近似解。由此可见,贪心算法只是追求某个范围内的最优,可以称之为“温柔的贪婪”。

2.3.2、为什么

从局部出发,将问题分解成若干个子问题,再求出这些子问题的最优解,然后将这些最优解合成最终解得到近似整个问题的最优解!以分解问题获得局部最优解的形式替代寻找整体最优解需要穷尽所有可能的算法可以节省大量时间。当然局部最优解并不一定是整体问题的最优解,所有要根据实际情况具体分析。

2.3.3、怎么用

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

2.3.4、总结

贪心算法不从整体最优上加以考虑,所做出的仅是在某种意义上的局部最优选择。一个问题的整体最优解可通过一系列局部的最优解的选择达到,并且每次的选择可以依赖以前作出的选择,但不依赖于后面要作出的选择。这就是贪心选择。

2.4、动态规划算法

2.41、是什么

动态规划法与分治法类似,其基本思想就是将问题分解成若干小问题,通过求解小问题从而得到原问题的解。其与分治法的区别在于分治法的子问题是相互独立的,而动态规划法的下一个子问题的求解是依托于上一个子问题的解的基础上进行的。也就是说问题的每个解决阶段是递推关系,比如问题1->问题2->问题3->解决问题。

2.4.2、为什么

与分治法类似,将问题分解,问题规模越小,消耗资源越少,将一个大问题划分成小问题,从而一步步获得最优解,提高程序执行效率。

2.4.3、怎么用

动态规划的主要难点在于理论上的设计,一旦完成设计,实现部分起始很简单!动态规划的设计一般要经理一笑几个步骤:
1) 问题划分:根据实际问题,将其有序的划分成若干个阶段性问题;
2) 阶段决策:求解各个阶段问题,需要确保阶段求解无后向性;
3) 确定却侧:因为决策和状态转移有着天然的联系,状态转移就是根据上一阶段的状态和决策来导出本阶段的状态。所以如果确定了决策,状态转移方程也就可写出。但事实上常常是反过来做,根据相邻两段各状态之间的关系来确定决策;
4) 寻找边界条件:给出的状态转移方程是一个递推式,需要一个递推的终止条件或边界条件。

2.4.4、总结

动态规划算法的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其他的算法。选择动态规划算法是因为动态规划算法在空间上可以承受,而搜索算法在时间上却无法承受,所以我们舍空间而取时间。

猜你喜欢

转载自blog.csdn.net/xianren95/article/details/126674531