编程珠玑第二章

编程珠玑第二章

A题

给定一个最多包含40亿个随机排列的32位整数的顺序文件,找出一个不在文件中一32位整数。

1、在文件中至少存在这样一个数?

2、如果有足够的内存,如何处理?

3、如果内存不足,仅可以用文件来进行处理,如何处理?

答案:

1、32位整数,包括-2146473648~~2146473647,约42亿个整数,而文件中只有40亿个,必然有整数少了。

2、如果采用位数思想来存放,则32位整数最多需要占用43亿个位。约512MB的内存空间。

可以采用前一章的位处理方法。然后判断每个int是否等于-1。因为-1的二进制表示是全1的。如果不等于-1。那么说明某一位没有置位。需要进行处理。

3、内存不足,可以采用如下思想:

1、按最高位分为两段,没有出现的那个数,肯定在比较小的段里面。

如果比较少的段最高位为1,那么缺少的那个数的最高位也为1.

如果比较少的段最高位为0,那么少的那个数的最高位也是0.

依次按以上方法去处理每个位。

算法复杂度为O(n)。每次处理的部分都是上一次的一半。累加之后是O(n).

思想与找第K小数的思想是一样的。只不过在这里是有一个自动分割的过程。而找第k小数的时候,是随机找一个数。

为了验证思想这里写了段C代码。

[cpp] view plaincopy

  1. int get_lost(int *a, int *b, int *c, int alen, int bit)
  2. {
  3. int re = 0, v = 0, biter = 0, *t, citer, i = 0;
  4. if (!a || !b || alen ==(unsigned long)( (1<< bit))) return -1;  //哪个数与最多可能拥有个数相等的时候,直接返回了。
  5. while (bit--)
  6. {
  7. v = (1 << bit);
  8. for (biter = citer = i = 0; i < alen; ++i)
  9. {
  10. if (a[i] & (1 << bit)) b[biter++] = a[i];
  11. else c[citer++] = a[i];
  12. }
  13. if (biter <= citer)
  14. {
  15. re += v;
  16. t = a; a = b; b = t;
  17. alen = biter;
  18. }
  19. else
  20. {
  21. t = a; a = c; c = t;
  22. alen = citer;
  23. }
  24. }
  25. return re;
  26. }

a, b, c,都是三个等长的数组,alen表示其长度。bit表示位数。比如32位。bit=32.

re表示最后缺少的那个数。

B题

字符串循环移位

比如abcdef 左移三位,则变成defabc

基本还是按照书上的算法,

_rev(0, i)

_rev(i, len)

_rev(0, len)

[cpp] view plaincopy

  1. static void _res(char *a, int n)
  2. {
  3. int i = 0, j = n - 1;
  4. char t;
  5. while (i < j)
  6. {
  7. t = a[i]; a[i] = a[j]; a[j] = t;
  8. ++i; --j;
  9. }
  10. }
  11. char *rever(char *a, int n, int len)
  12. {
  13. int i, j;
  14. if (!a || !n) return a;
  15. _res(a, n);
  16. _res(a + n, len - n);
  17. _res(a, len);
  18. return a;
  19. }

C 题

给定一个单词集合,找出可以相互转换的集合。

比如abc bca cba都可以相互转换。

算法如下

把由于每个单词可以进行唯一性标识,把这个单词按照字母进行排序,可以相互转换的单词都有同样的标识。

这里用C++来写了。

[cpp] view plaincopy

  1. void gen_label(vector<string> &dict, map<string, vector<string> >&rec)
  2. {
  3. for (int i = 0; i < dict.size(); ++i)
  4. {
  5. string line = dict[i];
  6. sort(line.begin(), line.end());
  7. rec[line].push_back(dict[i]);
  8. }
  9. for (map<string, vector<string> >::iterator iter = rec.begin();
  10. iter != rec.end(); ++iter)
  11. {
  12. copy((iter->second).begin(), (iter->second).end(), ostream_iterator<string>(cout , " "));
  13. cout << endl;
  14. }
  15. }

2.6习题

1 、如果没有时间进行预处理,那么可以找到这个单词的标识符,然后扫描这个字典,标识符相同的输出。

如果可以预处理,那么可以先预处理,用gen_label函数进行预处理则可。

2、把原来的程序取较大的部分则可。实际上如果要形成严格地每次下降一半,那么需要如下处理。

如果最多有max个整数,比如对于有4个bit位的整形数。最多有16个数。

如果给了32个数,实际上只需要取前面17个数就可以了,后面的不要了。

把这17个数按首位分为两堆,按理说一边是8,一边是9。如果发现分的一边比9还要多出几个。多出来的也不用看了。

接下来处理9个的情况。

通过这种策略,可以保证最终可以找到那个重复的数。

3、略过。这里涉及了一个效率不是那么高效的算法,不看也罢。

4、略过

5、如果是自己写函数那么就是前面所写的_rev函数。

如果是要调用rever()函数。那么方法如下。

[cpp] view plaincopy

  1. int main(void)
  2. {
  3. int n, len;
  4. char *c = NULL;
  5. while (scanf("%s", a) != EOF)
  6. {
  7. len = strlen(a);
  8. c = a;
  9. ++len;
  10. while (len--)
  11. {
  12. rever(c, len - 1, len);
  13. ++c;
  14. }
  15. printf("%s\n", a);
  16. }
  17. return 0;
  18. }

6、把名字对应的按键形成一个唯一的标识符,可以先对名字进行预处理。

用hash,

hash_map<int, hash_set<string> > rec;

7、 略过,记住按列再按行排序则可。

8、把最小的K个数找到O(nlogk),然后看这个K个数的和是否小于t.

9、搜索次数C > nlgn/ (n - lgn)

10、放到水中。

转自:http://blog.csdn.net/ju136/article/details/6839100

时间: 2024-10-07 13:23:19

编程珠玑第二章的相关文章

一维向量旋转算法 编程珠玑 第二章

看了编程珠玑第二章,这里面讲了三道题目,这里说一下第二题,一维向量旋转算法. 题目:将一个n元一维向量(例数组)向左旋转i个位置. 解决方法:书上讲解了5种方法,自己只想起来2种最简单方法(下面讲的前两种). 1.原始方法. 从左向右依次移动一位,对所有数据平移:这样循环i次,算法最坏时间复杂度达n^2.耗时不推荐. 2.空间换时间. 顾名思义,申请一个i长度的空间,把前i半部分放到申请空间中,再把后面的所有数据向左移动i个位置,最后把申请的空间中的数据放到后半部分.浪费空间,不推荐. 3.杂技

集体智慧编程_第二章(提供推荐)_1

前言:最近正在拜读Toby Segaran先生写的集体智慧编程,首先感谢Toby Segaran先生将知识以书本的方式传播给大家,同时也感谢莫映和王开福先生对此书的翻译,谢谢各位的不辞辛苦.首先在写随笔之前,跟各位分享一下我的编程环境:win7系统,python版本是2.7.10,开发环境我选择的是pycharm程序.本书的第一章为集体智慧导言,主要介绍的何为集体智慧和机器学习的相关概念和其局限性,以及与机器学习相关的例子和应用场景.下面开始机器学习第二章--提供推荐的相关内容. 本章主要内容:

java编程思想 第二章

这篇时间较之前篇章时间靠后,是由于,某一天晚上看完Java编程思想文献之后来不及做笔记了. 以下笔记基本为转载,不是原创 第二章   一切都是对象 目录: 2.1 用引用操纵对象 2.2 必须由你创建所有对象 2.3 永远不需要销毁对象 2.4 创建新的数据类型:类 2.5 方法.参数和返回值 2.6 构建一个Java程序 2.7 你的第一个Java程序 2.8 注释和嵌入式文档 2.9 编码风格 2.1 用引用操纵对象 一切都看作对象,操纵的标识符实际上是对象的一个“引用”,遥控器(引用)操纵

[书籍翻译] 《JavaScript并发编程》 第二章 JavaScript运行模型

本文是我翻译<JavaScript Concurrency>书籍的第二章 JavaScript运行模型,该书主要以Promises.Generator.Web workers等技术来讲解JavaScript并发编程方面的实践. 完整书籍翻译地址:https://github.com/yzsunlei/javascript_concurrency_translation .由于能力有限,肯定存在翻译不清楚甚至翻译错误的地方,欢迎朋友们提issue指出,感谢. 本书第一章我们探讨了JavaScri

对一千万条数据进行排序---编程珠玑第二版 第一章

本书第一章提出了一个看似简单的问题,有最多1000万条不同的整型数据存在于硬盘的文件中,如何在1M内存的情况下对其进行尽可能快的排序. 每个数字用4byte,1M即可存储250 000个数据,显然,只要每次对250 000个数据排序,写入到文件中即可,重复40次. 那么如何选出每次遍历的二十五万条数据呢?有如下两个策略: 1.对一千万条数据遍历40次,第i次遍历时,判断数是否属于[i*250000,i*250000+249999),如果是,则读入内存,当第i次遍历完成时,内 存中有了二十五万条数

编程珠玑第一章习题答案

习题 1.1      如果不缺内存,如何使用一个具有库的语言来实现一种排序算法? 因为C++有sort,JAVA也有,这里以C++为例给出,记住如果用set集合来排序时,是不可以有元素重复的 代码: #include <iostream> #include <cstring> #include <cmath> #include <queue> #include <stack> #include <list> #include <

java编程思想--第二章 一切都是对象

如果不做引申的话,本章没有多少可总结的内容.有些以前没有注意的细节可以写下来. 1.数据存储的位置 (1).寄存器.程序控制不了. (2).堆栈.对象的引用.基本类型. (3).堆.各种对象. (4).常量存储.和代码在一起. (5).非RAM存储.主要指流对象和持久化对象,前者准备网络传输,后者被丢到了硬盘上. 2.java中的数组会被自动初始化: (1).基本类型数组元素会被初始化为0 (2).引用类型数组元素会被初始化为null 3.变量作用域 (1).基本类型的跟C一样 (2).引用类型

Python核心编程_第二章课后习题

以下是自己在学习Python核心编程时,做的课后练习题.现在把它们贴出来,以记录自己的学习过程.小弟是机械出身,很多练习题目写的很是机械.虽然写出来的脚本都能满足题目要求,但效率可能不是最好的,所以,小弟还是厚着脸皮把它们给贴出来,一来可以让高手指点,二来可以与我一样在学习Python的兄弟共同学习. 以下的程序均以题目标号命名,如2-3这个题目,程序名就为2_3.py. 习题2_3.py #!/usr/bin/env python A = 10 B = 4 print "A plus B is

python核心编程2第二章课后练习

2-1 print来显示变量的内容,仅用变量名时,输出的字符串使用单引号括起来的,这是为了让非字符串对象也能以字符串的方式显示在屏幕上,print语句使用str()函数显示对象,交互解释器调用repr()函数来显示对象 2-2 (a)运算1+2*4 (b)只会做运算不会输出 (c)运算未显示结果 (d)交互解释器输入一段语句后会返回语句结果 (e)print ‘1+2*4’   2-3   2-4 (a) #!/usr/etc/env python string =raw_input("plea