简述
第三章 排序
章节开头先说明了排序在算法中的作用和地位。排序是非常多问题的子问题,所以排序算法很基础。
第一节通过给出排序的基本问题来引入了排序的算法,首先介绍的是最简单的时间复杂度为O(n^2)的冒泡算法,然后通过对冒泡算法的解析抛出了逆序这个概念,然后通过针对冒泡算法必须在相邻的元素之间进行排序的需求抛出了归并排序。不过并没有给出归并时合并的具体算法。然后提出了一个问题就是基于这种比较元素的算法还能比归并的O(nlogn)更好吗?随后通过一个树形结构论证了这是不可能的。注意是基于比较元素的算法不可能。也就是说这是针对一个普适性的排序问题的。然后举了一个计数排序(桶排序)的例子,针对这种情况的算法时间复杂度可以只有O(n)。
第二节介绍了在C++中的排序算法,标准库中的排序算法高效且方便。这里也没有什么tips值得注意,都是基操。
第三节介绍了二分搜索,排序后的数组可以使用二分搜索来提高元素的查找效率。作者分别列出了两种二分搜索的算法实现,这两种实现思想并不太一样。第一种是通过不停的将区间范围减半来实现的。第二种是一种探索性的踱步,在越靠近搜索的元素的时候走的步长越来越小。然后作者介绍了在C++中标准库的lower_bound和upper_bound函数。最后举了两个二分搜索典型应用,一是查找参数最小的解决方案。而是查找最大值。
第四章 数据结构
章节开头还是介绍了一下数据结构,给出了个本质的定义。然后说明了一下数据结构的选择创造对于解决具体问题是非常重要的。
第一节说明了一下动态数组(dynamic arrays),注意字符串是一种特殊的数组。还说明了标准库实现的使用,下面几节也各自说明了各自对应的标准库的使用。
第二节说明了一下集合(set),标准库中有四种实现,每种实现的集合类型不同,作用有些略微的区别,比如是否允许有重复的元素。需要注意的是这些不同数据结构的各种操作效率差别,下面几节同理。
第三节说明了一下映射(map),标准库中有两种实现,map和unordered_map,需要注意map插入效率为O(logn),而unordered插入效率为O(1)。
第四节说明了一下迭代器和范围(iterators and ranges),这个ranges我实在不知道怎么翻译好。主要就是说明了一下迭代器的使用。至于为什么会有迭代器这种东西,这需要慢慢领会,建议看C++标准库设计原理什么的,我也不是很懂。
第五节说明一些其他的数据结构,包括bitset(注意从右到左索引),双端队列(deque),队列(queue),优先级队列(priority queue),还有一个非标准库的数据结构indexed_set。在我的算法中常用的是优先级队列,真的太好用了…
第六节使用一个题作为例子,介绍了在问题的解决方案中,需要注意时间复杂度并不能说明一切,关键还是看细节。这个例子可以看看。
预告
接下来两章分别是完全搜索(complete search)和贪心算法(greedy algorithm)。
思考
从这几章所举例题,我们可以看出一个算法的改进往往是从一个最暴力的算法的提出开始的,在最暴力的算法中寻找问题解决方案的规律性,然后针对这些规律对算法进行优化。