From a127118e43a43fad7f739ed8c2211a8ca5d070cb Mon Sep 17 00:00:00 2001 From: Tiankai Ma Date: Tue, 11 Jun 2024 15:26:36 +0800 Subject: [PATCH] algo/hw1: update notes --- 7e1810-algo_hw/hw1.typ | 84 +++++++++++++++++++++++++++++++++++----- 7e1810-algo_hw/main.typ | 8 ++++ 7e1810-algo_hw/utils.typ | 15 +++++++ 3 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 7e1810-algo_hw/utils.typ diff --git a/7e1810-algo_hw/hw1.typ b/7e1810-algo_hw/hw1.typ index f2d3325..2ea2c16 100644 --- a/7e1810-algo_hw/hw1.typ +++ b/7e1810-algo_hw/hw1.typ @@ -1,12 +1,22 @@ +#import "utils.typ": * + == HW 1 (Week 2) Due: 2024.03.17 -#let ans(it) = [ - #pad(1em)[ - #text(fill: blue)[ - #it - ] - ] +#rev1_note[ + Review: 渐进符号 + + $o, O, Theta, omega, Omega$ 的定义如下: + + $ + O(g(n)) = {f(n) mid(|) exists c > 0, n_0 > 0, forall n >= n_0 quad 0 <= f(n) <= c dot g(n)}\ + o(g(n)) = {f(n) mid(|) exists c > 0, n_0 > 0, forall n >= n_0 quad 0 <= f(n) < c dot g(n)}\ + Theta(g(n)) = { + f(n) mid(|) exists c_1, c_2 > 0, n_0 > 0, forall n >= n_0 quad 0 <= c_1 dot g(n) <= f(n) <= c_2 dot g(n) + }\ + Omega(g(n)) = {f(n) mid(|) exists c > 0, n_0 > 0, forall n >= n_0 quad 0 <= c dot g(n) <= f(n)}\ + omega(g(n)) = {f(n) mid(|) exists c > 0, n_0 > 0, forall n >= n_0 quad 0 <= c dot g(n) < f(n)} + $ ] === Question 2.3-5 @@ -28,6 +38,10 @@ You can also think of insertion sort as a recursive algorithm. In order to sort A[i + 1] = key ``` + #rev1_note[ + 最坏情况是: 在排序 $[1,k]$ 时, 需要将 $A[k]$ 与 $A[1:k-1]$ 中的所有元素比较一次, 以确定插入位置. 这样, 在排序 $[1,n]$ 时, 需要比较的次数为 $1 + 2 + dots.c + (n-1) = Theta(n^2)$. + ] + The recurrence for its worst-case running time is $ @@ -35,7 +49,6 @@ You can also think of insertion sort as a recursive algorithm. In order to sort $ The solution to the recurrence is $Theta(n^2)$ worst-case time. - ] === Question 2-1 @@ -51,6 +64,7 @@ Although merge sort runs in $Theta(n lg n)$ worst-case time and insertion sort r #ans[ + For each sublist, the insertion sort can sort the $k$ elements in $Theta(k^2)$ worst-case time. Thus, the insertion sort can sort the $n\/k$ sublists, each of length $k$, in $Theta(n k)$ worst-case time. + + Given $n\/k$ sorted sublists, each of length $k$, the recurrence for merging the sublists is $ T(n) = cases(2 dot.c T(n\/2) + Theta(n) space.quad & n>k, 0 & n=k) @@ -59,6 +73,16 @@ Although merge sort runs in $Theta(n lg n)$ worst-case time and insertion sort r *This could also be viewed as a tree with $lg(n\/k)$ levels with $n$ element in each level. Worst case would be $Theta(n lg (n\/k))$* + #rev1_note[ + 将 $n\/k$ 个数组看成 $n\/k$ 个元素, 作为 merge sort 的叶节点. 这样一个数有 $n\/k$ 个叶节点, 也就有 $log(n\/k)$ 层. 每层实际上合并 $n$ 个元素, 总时间复杂度为 $Theta(n lg(n\/k))$. + + 直接进行 $n\/k-1$ 次合并是不可行的, 这样的速度在 $Theta(n^2\/k)$, 不符合要求. + + 另一种可行的思路: 考虑直接合并 $n\/k$ 个有序数组, 我们比较这 $n\/k$ 个数组中, 尚未取出的最小元素, 并从中选取最小元素. + + 具体来说, 维护一个 $n\/k$ 大小的 heap 和一个 $n\/k$ 大小的数组, 用于存储每个数组中的当前元素. 每次取出堆顶元素, 并将对应数组的下一个元素插入堆中. 这样, 每次取出最小元素 (构建最小堆) 的时间复杂度为 $O(lg(n\/k))$, 总时间复杂度为 $O(n lg(n\/k))$. + ] + + Take $Theta(n k + n lg(n \/ k)) = Theta(n lg n)$, consider $k = Theta(lg n)$: $ Theta(n k + n lg(n \/ k)) @@ -66,16 +90,58 @@ Although merge sort runs in $Theta(n lg n)$ worst-case time and insertion sort r &= Theta (n lg n + n lg n - n lg (lg n)) \ &= Theta (n lg n) $ + + #rev1_note[ + 思路: + $ + Theta(n k +n log(n\/k))=O(n log n) + $ + 只需令 $k, log(n\/k) = O(log n)$ 就能满足条件. 这样我们得到 $k=o(1)=O(log n)$, 选取最大边界 $k=Theta(log n)$, 通过上述验证可以发现严格记号成立, 那么最大的 $k$ 值为 $Theta(log n)$. (渐进意义上的.) + + 容易发现当 $k=o(log n)$ 时, $Theta(n k + n log(n\/k))=o(n log n)$, 这样的 $k$ 值不满足题目要求. + ] + + Choose $k$ to be the largest length of sublist for which insertion sort is faster than merge sort. Use a small constant such as $5$ or $10$. + #rev1_note[ + 这里的主要问题是, 比较两个 $Theta$ 意义下相等的算法用时必须考虑常数, 实践中可以通过记录算法实际运算次数得到. + ] +] + +#rev1_note[ + Review: 主定理 + + 对分治算法的递归式 + + $T(n) = a T(n / b) + f(n)$ + + 主定理给出了一个快速求解递归算法复杂度的复杂度: + + 1. 如果 $f(n) = O(n^c)$, 其中 $c < log_b a$, 则 $T(n) = Theta(n^{log_b a})$. + ] === Question 4.2-3 -What is the largest $k$ such that if you can multiply $3 times 3$ matrices using $k$ multiplications (not assuming commutativity of multiplication), then you can multiply $n times n$ matrices in $o(n lg 7)$ time? What is the running time of this algorithm? +What is the largest $k$ such that if you can multiply $3 times 3$ matrices using $k$ multiplications (not assuming commutativity of multiplication), then you can multiply $n times n$ matrices in $o(n^(log 7))$ time? What is the running time of this algorithm? #ans[ + #rev1_note[ + 稍微翻译一下题目: + + 如果你有一个 $k$ 次乘法的 $3 times 3$ 矩阵乘法算法, 那么这样的算法是否能否构造一个, 在 $o(n^(log_2 7))$ 时间内完成 $n times n$ 矩阵乘法? 问满足条件的最大的 $k$ 是多少. + + 递归式是 $T(n) = k T(n\/3) + O(n^2)$, 我们分类讨论来使用主定理: + + // - $k=27$ 时这就是最基本的矩阵分块算法. 我们不妨假设 $k<27$. + + - $log_3 k < 2$, 正则化条件: $k dot (n\/3)^2 < n^2$ 即 $k < 9$, 算法规模在 $T(n)=O(n^2)subset O(n^(log_2 7))$. + - $log_3 k = 2$, 此时 $T(n)=O(n^2 lg n) subset O(n^(log_2 7))$. + - $log_3 k > 2$, 为使 $T(n)=O(n^(log_3 k)) subset O(n^(log_2 7))$, 需要 $log_3 k < log_2 7$, 最大的 $k=21$. + + 下面这个答案中递归式是错误的, 应该改正. + ] + Assuming $n = 3^m$. Use block matrix multiplication, the recursive running time is $T(n) = k T(n\/3) + O(1)$. When $log_3 k > 2 $, using master theorem, the largest $k$ to satisfy $log_3 k < lg 7$ is $k=21$. - ] \ No newline at end of file diff --git a/7e1810-algo_hw/main.typ b/7e1810-algo_hw/main.typ index 07ce9b0..8d350ab 100644 --- a/7e1810-algo_hw/main.typ +++ b/7e1810-algo_hw/main.typ @@ -1,6 +1,8 @@ #import "@preview/cetz:0.2.2": * #import "@preview/diagraph:0.2.1": * +#import "utils.typ": * + #set text( font: ("linux libertine", "Source Han Serif SC", "Source Han Serif"), size: 10pt, @@ -22,6 +24,12 @@ 本文档以 CC BY-NC-SA 4.0 协议发布. 请遵守学术诚信, 不得用于商业用途. + #rev1_note[ + \* Revision 2024/06/11: 随期末复习增加了一些注释性内容, 以红色标注. + + 参考了助教答案中的部分内容, 在此表示感谢. + ] + #image("imgs/sticker_1.jpg", width: 30%) ] diff --git a/7e1810-algo_hw/utils.typ b/7e1810-algo_hw/utils.typ new file mode 100644 index 0000000..958fdae --- /dev/null +++ b/7e1810-algo_hw/utils.typ @@ -0,0 +1,15 @@ +#let ans(it) = [ + #pad(1em)[ + #text(fill: blue)[ + #it + ] + ] +] + +#let rev1_note(it) = [ + #pad(1em)[ + #text(fill: red)[ + #it + ] + ] +] \ No newline at end of file