《编程珠玑》读书笔记
Chapter 1
问题:文件包含1千万条记录,每条记录是7位的整数,可用内存为1MB,对这个文件进行排序。
解法1:估算1MB的空间可以存储25万个号码,第一趟遍历0-249999之间的任何整数,并对这25万个整数进行排序,到第40趟遍历时就可以对这一千万记录排序完毕。代价读取输入文件40次,写输出文件1次,无需中间文件辅助。
解法二:归并排序读取输入文件1次,分成n(n>40,根据可用内存选择具体大小,每个部分可以读入内存完成排序)个中间文件,每次对其中一个文件读入排序后写回,最后使用归并把n个中间文件合并成一个文件。代价是读取输入文件1次,写输出文件1次,需要多次读写中间文件。
解法三:
7位整数表示一个小于1000万的整数。我们把这个文件的记录用1000万个bit来表示。
这个表示利用了该问题的三个在排序问题中不常见的属性:
1.输入数据限制在相对较小的范围内;
2.数据没有重复;
3.对于每条记录而言,除了单一整数外,没有任何其他关联数据。
其实这个解法利用的是计数排序(最大计数为1)的原理。
这种使用一个bit来标记一个元素的方法称为bit map,布隆过滤器是其扩展版本,它们在处理海量数据中经常使用。
对小问题的仔细分析有时可以得到明显的实际益处
Chapter 2
问题A:给定一个40亿个随机排列的32位整数的顺序文件,找出一个不在文件中的32位整数(在文件中至少缺失一个这样的数,因为2的32次方大于40亿)。在具有足够内存的情况下如何解决该问题?如果有几个外部的”临时“文件可用,但是仅有几百字节的内存,又该如何解决该问题?
(1)在有足够内存的情况下可以使用前面的bit map来解这个问题。
(2)内存不足时,使用二分法,利用二分法比较巧妙,不太容易想到。(这里要摒弃固定思维,二分法并不是什么情况下都需要排序后才能使用)
二分法思想是这样的:我们读取记录并从中取出一个数字,将高位为1,以及高位为0两类放到不同文件里,这个过程不需要多少工作内存,几十个byte足够。 我们假设高位为1的放入文件1中;为0的放入文件0中。按最高位分为两段,没有出现的那个数,肯定在比较小的段里面。 如果比较少的段最高位为1,那么缺少的那个数的最高位也为1。如果比较少的段最高位为0,那么少的那个数的最高位也是0。依次按以上方法去处理每个位。
问题B:将一个n元一维向量向左旋转i个位置,原地并在O(N)时间内完成。
问题C:给定一个英语字典,找出其中所有的变位词集合。
解法:使用基于排序的标识,变位词经过按照字母表排序后可以得到相同的标识。
Chapter 3
恰当的数据视图实际上决定了程序的结构,下面的两段程序实现的逻辑是相同的,但是第二种实现更简洁。
if k == 1: c001 += 1
if k == 2: c002 += 1
...
if k == 500: c500 += 1
arr = [0 for i in range(500)]
for i in numbers:
arr[i]+=1
其他部分没什么价值,省略
重点:部分习题答案 P205
posted on 2019-08-28 16:46 Frank_Allen 阅读(341) 评论(0) 编辑 收藏 举报