常用算法总结
程序是为了具体的问题而存在,每个具体问题可抽象为一定的数学问题即算法的表示。故有了下面的公式:
程序 = 数据结构 + 算法 + 程序设计语言
数据结构表示要处理的数据;算法表示核心的处理流程;程序设计语言完成和具体业务化的问题。
常用的基本算法有以下这些:
1. 枚举算法
枚举法,将可能的所有解一一枚举出来,每个去算法中计算,得出正确的解。
但是该算法效率不是很高,适用于一些没有明显规律的环境。
难点在于如果枚举出所有可能的输入。
算法思路:
- 对于一种可能的情况,计算其结果。
- 判断结果是否满足需求,如果不满足要求,找出下一个可能的解代入第1步。如果满足,则表示找到1个正确的解。
2. 递推算法
递推算法适用于有明确数学公式的情况,即通过已知条件,利用特定关系得出中间推论,直至得到结果的算法。
递推算法分为顺推和逆推两种。
算法思路:
1.顺推法:从已知条件出发,逐步推算出要解决的问题的方法叫顺推。
典型的场景有:斐波那契数列.
2. 逆推法:从已知问题的结果出发,用迭代表达式逐步推算出问题的开始的条件,即顺推法的逆过程,称为逆推。
典型的场景有:分蛋糕问题
3. 递归算法
递归算法,就是一种直接或者间接地调用自身的算法。
递归算法的具体实现过程一般通过函数(或子过程)来完成,在函数(或子过程)的内部,编写代码直接或者间接地调用函数(或子过程)自己,即可完成递归操作。
算法思路:
把求解问题转化为规模缩小了的同类问题的子问题,然后递归调用函数(或子过程)来表示问题的解,通过多次递归调用,最终可求出最小问题的解,然后通过这个最小问题的解返回上层调用,再求出次小问题的解,再返回上层调用,不断重复,最终得到整个问题的解,完成递归操作
注意:递归算法必须有明确的递归出口。
4.分治算法
分治算法即把复杂问题简单化,一个复杂的问题拆分为几个相对简单的子问题,如果子问题依然无法解决,再次分割。直到能够解答问题为止。听起来好像和递归算法没有什么区别一样?这两者的差异在于分治法使用的子过程可以为多个,而递归只能是1个。在子问题一致时,两者几乎一致。而分治法产生的子问题,一定程度上和父问题相似,比较方便配合递归方法使用。
算法思路:
对于一个规模为N的问题,若该问题可以容易地解决(比如说规模N较小),则直接解决,否则将其分解为M个规模较小的子问题,这些子问题互相独立,并且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。
故分治法会有3个典型步骤:分解,求解,合并。分治法的分解和合并步骤会影响其复杂度。
5.贪婪算法
贪婪算法是不考虑整体的情况下,只针对局部问题最优解的算法。一般情况下,贪婪算法的解不一定是问题的最优解。优势是能够节省时间。贪婪算法一般不需要回溯。
算法思路:
贪婪算法的基本思路:从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快地求得更好的解。当达到算法中的某一步不能再继续前进时,就停止算法,给出近似解
由贪婪算法的特点和思路可看出,该算法存在以下问题:
- 不能保证最后的解是最优的;
- 不能用来求最大或最小解问题;
- 只能求满足某些约束条件的可行解的范围。
6.试探算法
试探算法也叫回溯算法:为了求得问题的解,先选择某一种可能情况进行试探,在试探过程中,一旦发现原来选择的假设情况是错误的,就退回一步重新选择,继续向另一个方向试探,如此反复进行,直至得到解或证明无解。
以上这些基本就是算法设计中的基本思路:复杂问题分割为子问题或者分步骤,每个子问题寻找简单的解决办法。可能分治法需要优先考虑,将问题分解后,每个子问题再寻找解决方案,评估解决方案的准确性和算法复杂度时,决定采用贪婪还是回溯方法得到可以接受的解决方案。