一、分治法
分治法即“分而治之法”,核心思想就是讲一个难以直接解决的大问题依照相同的概念,分割成两个或更多的子问题,以便各个击破。问题的规模越小,越容易直接求解,使子问题的规模不断缩小,直到这些个子问题足够简单到可以解决,最终再将各子问题的解合并得到原问题的最终解答。
分治法的应用相当广泛,如快速排序、递归算法、大整数乘法。
二、递归法
递归是一种特殊的算法,和分治法很像,都是将一个复杂的算法问题进行分解,让规模越来越小,最终使子问题容易求解。在递归算法中,函数不单能够被其他函数调用,它还提供了自己调用自己的功能。
递归的正式定义:一个函数或子程序,是由自身所定义或调用的,就称为递归。递归至少要满足2个条件:一个是可以反复执行的递归过程,另一个是可以离开递归执行函数的出口。
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return (fib(n-1)+fib(n-2))
n = int(input('请输入要计算第几项的斐波那契数列:'))
for i in range(n+1):
print('fib(%d)=%d' %(i,fib(i)))
三、贪心法
贪心法是从某一起点开始,在每个解决问题步骤中使用贪心原则,即采取在当前状态下最有利或最优化的选择,不断地改进该解答,持续在每一个步骤中选择最佳的方法,并且逐步逼近给定的目标,当达到某一步骤不能再继续前进时,算法就停止。
贪心算法的思想是把求解的问题分成若干子问题,但这不能保证求得的最后解是最佳的。贪心法容易过早作出决定,只能求满足某些约束条件下可行解的范围。当然对有些问题可以得到最佳解。
贪心法常用于找出图的最小生成树(MST)、最短路径与哈夫曼编码等。
四、动态规划法
动态规划法类似于分治法,它的主要做法:如果一个问题答案与子问题相关的话,就能将大问题拆解成各个小问题,其中与分治法不同的是可以让每一个子问题的答案被存储起来,以供下次求解时直接取用。这样的做法不但能减少再次计算的时间,并可将这些解组合成大问题的解答,故而使用动态规划可以解决重复计算的问题。
#动态规划法
output = [None]*1000 #fibonacci的暂存区,内容为空
def fib_DPA(n):
result = output[n]
if result == None:
if n == 0:
result = 0
elif n == 1:
result = 1
else:
result = fib_DPA(n-1) + fib_DPA(n-2)
output[n] = result
return result
n = int(input('请输入要计算第几项的斐波那契数列:'))
for i in range(n+1):
print('fib(%d)=%d' %(i,fib_DPA(i)))
五、枚举法
枚举法又称穷举法,是一种常见的数学方法,它的核心思想是列举所得可能。根据问题要求,逐一列举问题的解答,或者为了便于解决问题,把问题分为不重复、不遗漏的有限中情况,逐一列举各种情况,并加以解决,最终到达解决整个问题的目的。该算法的缺点就是速度太慢。
六、回溯法
回溯法也算枚举法的一种,对于某些问题来说,回溯法是一种可以找出所有(或一部分)解的一般性算法,同时避免枚举不正确的数值。一旦发现不正确的数值,就不再递归到下一层,而是回溯到上一层,以节约时间,是一种走不通就退回再走的方式。它的特点是在搜索过程中寻找问题的解,当发现不满足求解条件时,就回溯,尝试别的路径,避免无效搜索。