update thu_dsa/chp1.md, adding more conclusions.

This commit is contained in:
Shine wOng
2019-10-16 22:28:13 +08:00
parent 4da83c0bd8
commit be364e9f25
3 changed files with 13 additions and 4 deletions

View File

@@ -188,9 +188,21 @@ _若存在函数f(n)和正的常数c1和c2使得在渐进的条件(n >> 2)下
在有了一个可以运行的版本后,再分析已有程序的运行过程,对其进行优化,比如规避递归程序的冗余,或者利用栈模拟操作系统的函数栈,写一个非递归的代码。这整个过程就是动态规划。
关于动态规划,主要是有几个例子
关于动态规划,最关键的内容还是把握它的思想,并将其应用到客观世界的复杂问题中,这个在习题集中有详细的内容。其中主要是有几个例子
+ 斐波拉契数
+ LCS
可以查看邓公的网课和讲义,我自己也有代码实现。
为了把握这里的`fib()`和`lcs`相关的算法,关键在于把握它们各个版本算法之间的联系,即原来的递归版本存在什么问题,因此新的迭代版本就这个问题进行了优化。比如`lcs`算法,根据它的定义,不难给出一个递归版本的算法,但是通过对该算法进行分析,发现居然需要`O(2^n)`的时间复杂度,深入分析发现它的低效是由于大量实例的重复计算,可以注意到,在递归过程中实际上只涉及`O(m*n)`个不同的实例,一种思想是把所有这些实例都预先计算出来,然后制表备查;另一种思想则是颠倒递归计算的次序,改为自底向上迭代,即动态规划的方法。另一个方面就是需要把握各个版本的时空复杂度,主要就是利用上面`递归跟踪`和`递推公式`的方法。最后,为了求出`lcs`的具体组成而非仅仅是长度,我自己设计了一个精巧的算法,在[习题集解答](exercises.md)中有详细的说明。
对于`fib`的各个算法,这里就不再赘述。需要把握的要点有
+ 二分递归版本算法及其复杂度分析
+ 线性递归版本算法及其复杂度分析
+ 上述两个算法之间的联系,线性递归版本的本质乃是在`fib()`中同时返回`fib(n)`和`fib(n-1)`。
+ `O(n)`的迭代版算法
+ 基于优化的`power`函数的`O(logn)`的迭代版算法,它的基本公式的推导,`power`函数的几个优化版本以及它们之间的关联,时间复杂度的分析
类似的思路也适用于教材和习题集中的一个`countOnes`函数,它也有三个版本两个优化版本,不过这里除了它们内在的联系以及复杂度分析以外,还需要注意一下其中精巧的位运算操作。

View File

@@ -114,5 +114,3 @@ string lcsIt(string one, string two, int len1, int len2){
}
return lcs;
}

View File

@@ -75,4 +75,3 @@ void test_lcslenRe(){
cout << "Recursive lcs test passed." << endl;
cout << "Running time: " << end - begin << endl;
}