本人大四即将结束,于2018年12月18日购《算法导论》这本书,慢慢看,第一阶段先主要理解各个章节说的算法都是什么意思,书上的课后习题先不做,用得上什么算法我再详细学习。这是官方课后答案的链接。
放在开头:没有好的算法,坏的算法之说,重点是针对不同的情况,针对不同的数据,针对不同的需求,去选择算法,改良算法。我的数学功底不强,太难的公式我看不懂,太高深的思想我理解不了,我主要以应用为主,不以解释数学公式为主。
动态规划(dynamic programming)与分治方法相似,而且很像在第一章介绍的Strassen算法,都是通过组和子问题来求解原问题。
分治算法是将问题划分成互不相交的子问题,然后递归的求解子问题。相反,动态规划应用于子问题的重叠情况,就是说,我们在求解一个不是最小规模的子问题时,往往会做很多“重复工作”,这就造成了不必要的时间浪费。
动态规划属于一种空间换时间的算法:为了让程序高效的运行,它会通过一些方式,提前储存好一些子问题的答案,使用的时候,直接查找就行了。
动态规划
这个方法不是什么问题都适合的,用的时候要注意是否满足条件。
1、最优子结构:整体的最优解是由子问题的最优解组成的,子问题之间的资源是独立的。
2、子问题重叠:递归算法反复求解相同的子问题。
在此提出了两种实现动态规划的方法:
1、带备忘的自顶向下法:
还是自然地递归形式编写程序,但是过程会保存每个子问题的解,通常保存在一个数组或者散列表中。当需要一个子问题的解时候,我们检查是否保存过这个解。如果是,就直接返回保存的数,从而节省了时间;否则正常递归。
2、自底向上法:
我们定义好最子子子子问题的规模后,保证我们对任何问题的求解都只依赖我们所定义的规模。我们将子问题从小到大求解,当求解到某个子问题时候,更小的子问题都已经求解完毕了。
通常情况下,如果每个子问题都得至少求解一次,自底向上比自顶向下要好,因为自底向上算法没有递归调用的开销。相反,如果子问题空间中的某些子问题完全不必求解,自顶向下法会更好一些,因为它只会求必要的子问题。
应用方案
本章一共介绍了4种应用方案(都是递归不行,用动态规划解决的)
1、钢条切割问题(怎么切,切多少,卖的钱最多)
2、矩阵链乘问题(设计矩阵的相乘顺序,怎么乘,计算量少,运算速度最快)
3、最长公共子序列问题(在两个序列中,找到他们最长的公共的子序列,就像找两个数的最大公约数)
4、最优二叉搜索树(每个树结点都有不同的搜索权重,选哪个树结点为根节点,我们想要的搜索速度才能最快)