zoukankan      html  css  js  c++  java
  • 《编程珠玑》读书笔记

    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)时间内完成。

    [(a^rb^r)^r = (ba) ]

    问题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

  • 相关阅读:
    Text Link Ads 注册[赚钱一]
    Linux文件系统中的链接
    C++虚函数和纯虚函数(1)
    Android init reading tips
    Android上GDB的使用
    What is prelink?
    Linux fork哪些被继承,哪些不被继承
    为什么x86 Linux程序起始地址是从0x08048000开始的?
    Android应用开发的插件化 模块化
    C++拷贝构造函数(深拷贝、浅拷贝)
  • 原文地址:https://www.cnblogs.com/ZeroTensor/p/11424961.html
Copyright © 2011-2022 走看看