斯坦福 Algorithms: Design and Analysis 2 第一周笔记
来自斯坦福网站的Algorithms: Design and Analysis,与目前coursera上的版本内容没有变化,不过时间安排略有不同。
1. Introduction
这里介绍了两个比较经典的算法问题作为引子,在这么课中将会学会解决这两个问题的算法。
1.1 Internet routing
因特网与图这个数据结构非常有关系。因特网本身可以看成一个图,结点是每个主机以及每个路由器,边是每个节点之间相连的网线或者无线网。而网络中还有其它可以看成图的,比如网页图。每个网页看成一个节点,网页间的超链接看作是边。还有社交网络等等。
网络路由问题:
假设从斯坦福的网关路由器发送数据到康奈尔,需要选择一条最短的传播路径,假设传播的跳数最少就是最短。那么这就是图中的一个最短路径问题。算法1中讲到的dijkstra算法可以解决这个问题,但是这个算法需要每个路由器知道全局信息,但这是不可能的。我们需要一个只知道local信息(与其相连的结点信息)就能得到最短路径的算法,这就是贝尔曼福特算法。
1.2 sequence alignment
序列对齐问题:假设有两个字符串序列,需要判断它们相似的程度。相似的定义是,两个字符串对齐之后完全相同的字符所占比重。需要插入空格和对齐后的字符不相等都算是penalty。两个字符串对齐之后的penalty越小就说明它们越相似。这个penalty叫做NW score。
于是我们需要一个算法来计算两个字符串的对齐。如果有两个长度为500的字符串,使用暴力做法尝试所有可能的对齐方式,这个复杂度是 2 500 2^{500} 2500,永远不可能实现。但是使用动态规划就可以很快解决这个问题。
2. Greedy Algorithms
2.1 Introduction
这部分介绍了贪心算法。贪心算法是四种算法的设计思想之一,这四个思想为:
- 分治法
- 随机算法
- 贪心算法
- 动态规划
贪心算法没有一个严格的定义,大致的意思是说,算法在当前情形下选择目前看来最好的选择,期望这么做到最后得到的结果也是最好的。一个例子就是dijkstra算法。
和分治法有很多不同点:
- 分治法对每个问题都需要有具体设计,贪心法是个很容易用到不同问题的方式。
- 分治法时间复杂度分析很困难,贪心法一般很简单。
- 分治法正确性比较容易证明,贪心法一般很难证明。
DANGER:大部分贪心算法都不正确。
比如虽然dijkstra算法是对的,但在有负权重的情况下继续贪心就会导致错误:
正确性证明的几种方式:
- Induction(貌似包括演绎法与归纳法):比如dijkstra算法的证明。
- exchange argument:貌似指的是反证法,但感觉不完全是。意思就是假设一个最优解,然后与算法得到的解交换一些元素,得到矛盾就是反证法。也有可能会直接推导出算法当前解同样也是最优的。
- 其它任何方法。
2.1.1 Optional Caching
缓存的替换机制就是贪心法的一个应用。
缓存的替换不再介绍,但是缓存的替换有一个最优的指导原则,那就是去掉当前缓存中在未来被再次访问时距离当前时间最远的页。最优指的是类似缓存的访问miss最少。
不过算法不会预知未来,这个原则的意义在于:1.可以作为真实算法的指导。比如可以用这个原则知道利用data的locality性质LRU算法会效果更好一些。 2. 可以做一些用来测试的benchmark。
2.2 A SCHEDULING APPLICATION
一个调度问题定义为:有共享的资源(如一个处理器),有很多job需要做(如处理线程)。问题是该如何给这些job进行调度排序。可以假设每个job有一个表示优先度的weight,以及处理时间l。每个任务有个完成时间 C j C_{j} Cj,表示当前任务以及之前所有任务的时间和。调度任务的目标函数是让完成时间的加权和最小,即 m i n ∑ j = 1 n w j C j min\sum_{j=1}^{n}w_{j}C_{j} min∑j=1nw