您的位置:首页 > 其它

2014年阿里巴巴9月14号笔试题

2014-09-27 15:38 288 查看
一、单选题

  1.假设把整数关键码K散列到N个槽列表,以下哪些散列函数是好的散列函数

A: h(K)=K/N;

B: h(K)=1;

C: h(K)=K mod N;

D: h(K)=(K+rand(N)) mod N, rand(N)返回0到N-1的整数

选择C,解释:hash的特性在于常数的时间执行插入、删除和查找操作,用D作为hash函数无法满足该条件,因为函数的返回值不确定,这样无法进行正常的查找。用C产生碰撞可以用链接法解决冲突

2.下面排序算法中,初始数据集的排列顺序对算法的性能无影响的是:

A: 堆排序 B:插入排序 C: 冒泡排序 D:快速排序

选择A,解释:(1)堆排序的时间复杂度一直都是O(nlogn),不稳定(2)插入排序在初始有序情况下,时间复杂度为O(n),平均时间复杂度为O(n^2),稳定排序(3)冒泡排序在初始有序的情况下,增加交换标示flag可将时间复杂度降到O(n),稳定排序(4)快速排序在初始有序的情况下,可能会退化到O(n^2),不稳定排序

3. 下面说法错误的是:

A: CISC计算机比RISC计算机指令多

B: 在指令格式中,采用扩展操作码设计方案的目的是为了保持指令字长不变而增加寻址空间

C:增加流水线段数理论上可以提高CPU频率

D:冯诺依曼体系结构的主要特征是存储程序的工作方式

 选择B,解释(1)CISC复杂指令集,RISC精简指令集,从名字上就可以得出A正确(2)保持指令字长度不变而增加指令操作的数量(3)看样子都觉得正确(4)冯诺依曼体系结构的主要特点:存储程序控制(要求计算机完成的功能,必须事先编制好相应的程序,并输入到存储器中,计算机的工作过程是运行程序的过程);程序由指令构成,指令和数据都用二进制表示;指令由操作码和地址码构成;机器以cpu为中心

4. 不属于冯诺依曼体系结构必要组成部分是:

 A:CPU B: Cache C:RAM D:ROM

 B,解释:冯诺依曼体系结构必要组成部分:运算器、控制器、存储器、输入设备、输出设备,Cache属于缓存了

6.你认为可以完成编写一个C语言编译器的语言是:

A:汇编 B:C语言 C:VB D:以上全可以

D,解释:其实你学好编译原理用什么语言都能写出来

7. 关于C++/JAVA类中的static成员和对象成员的说法正确的是:

A:static成员变量在对象构造时候生成

B: static成员函数在对象成员函数中无法调用

C: 虚成员函数不可能是static成员函数

D: static成员函数不能访问static成员变量

C,解释:(1)类的static成员变量属于该抽象类,需要在类定义时初始化,不可以在对象的构造函数中初始化。static成员变量可以直接定义,例如public statci $a = 10; 所以A错(2)static成员函数在对象成员函数中可以调用,同属于一个类作用域,在对象成员函数里可以通过类名::static函数名的方法调用(4)static成员函数只能够访问static 成员变量,同样道理,类名::static成员变量名,这也是访问static成员变量唯一的方法(3)是正确的

8,假设下图中每个正方形的边长为1,则从A到Z的最短路径条数为



A,11 B,12 C,13 D,14

C,解释

9:某进程在运行过程中需要等待从磁盘上读入数据,此时进程的状态将:

A: 从就绪变为运行 B:从运行变为就绪 C: 从运行变为阻塞 D:从阻塞变为就绪

C,解释:I/O事件让进程从running->waitting

10:下面算法的时间复杂度为:

int f(unsigned int n)

{

if(n==0||n==1)

return 1;

else

return n*f(n-1);

}

A: O(1) B:O(n) C:O(N*N) D:O(n!)

B,解释:共执行n次乘法,即n*(n-1)*....*1,T(n)=O(n)

11: n从1开始,每个操作可以选择对n加1或者对n加倍。若想获得整数2013,最少需要多少个操作。

A:18 B:24 C:21 D;不可能

A,解释:可以把2013倒推,奇数减1,偶数除以2,最后可以推出需要18步。或者编程实现是一个明显的bfs题目,编程实现为18

 12:对于一个具有n个顶点的无向图,若采用邻接表数据结构表示,则存放表头节点的数组大小为:

A: n B: n+1 C: n-1 D:n+边数

A,解释:理解无向图用邻接表存储的方式

13.考虑一个特殊的hash函数h,能将任一字符串hash成一个整数k,其概率p(k) = 2^(-k),k = 1,2,3,4,....对于一个未知大小的字符串集合S中的每一个元素取hash值所组成的集合为h(S).若h(s)中最大元素max h(s) =10,那么s的大小期望是

A:1024 B:512 C:5 D:10

A,解释:每个字符串取hash可以看成同分布的独立函数,每个时间出现的10的概率为1/1024,故期望为1/p。

14.如下函数,在32bit系统foo(2^31-3)的值是:

 int foo(int x)

{

return x&-x;

}

A: 0 B: 1 C:2 D:4

 C,解释:2^31即0000 0010 ^ 0001 1111结果为0001 1101即29,29-3=26,-x即-26在计算机存储为补码1110 0110,x=26在计算机存储为原码:0001 1010,再经过与得0000 0010,即为2

16:在32为系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是:

Struct A

{

int a;

short b;

int c;

char d;

};

Struct B

{

int a;

short b;

char c;

int d;

};

A: 16,16 B:13,12 C:16,12 D:11,16

C,解释:结构体的长度必须为最大成员长度的整数倍,int 4个字节,short 2个字节,char 1个字节

  对于A:

int a自身对齐是4,pragma pack指定对齐也是4,因此其有效对齐为4,起始地址0x0000满足0x0000 % 4 == 0

short b自身对齐是2,指定对齐是4,因此有效对齐为其最小值2,起始地址0x0004满足0x0004 % 2 == 0

int c自身对齐是4,pragma pack指定对齐也是4,因此其有效对齐为4,起始地址0x0006不满足0x0006 % 4 == 0,因此需要填充空字节,起始地址为0x0008

char d自身对齐是1,指定对齐是4,因此有效对齐为其最小值1,起始地址0x000C满足0x000C % 1 == 0

结构体还需要整体对齐,也就是结构体成员最大有效对齐的倍数,0x000D不满足 % 4 ==0, 需要需要补充3个字节,总字节数为16

对于B:

int a自身对齐是4,pragma pack指定对齐也是4,因此其有效对齐为4,起始地址0x0000满足0x0000 % 4 == 0

short b自身对齐是2,指定对齐是4,因此有效对齐为其最小值2,起始地址0x0004满足0x0004 % 2 == 0

char d自身对齐是1,指定对齐是4,因此有效对齐为其最小值1,起始地址0x0006满足0x000C % 1 == 0

int c自身对齐是4,pragma pack指定对齐也是4,因此其有效对齐为4,起始地址0x0007不满足 % 4 ==0,需要补充一个空字节,起始地址为0x0008

结构体需要整体对齐,结构体整体有效对齐是4,0x000C % 4 == 0,因此总字节为12

18:一个洗牌程序的功能是将n张牌的顺序打乱,以下关于洗牌程序的功能定义说法最恰当的是:

A: 每张牌出现在n个位置上的概率相等

B: 每张牌出现在n个位置上的概率独立

C: 任何连续位置上的两张牌的内容独立

D: n张牌的任何两个不同排列出现的概率相等

19:用两种颜色去染排成一个圈的6个棋子,如果通过旋转得到则只算一种,一共有多少种染色:

A: 10 B:11 C:14: D:15

设黑白两种颜色N(n)表示有n个黑色的种类

N(0)=N(6)=1;

N(1)=N(5)=1;

N(2)=N(4)=3;黑黑白白白白,黑白黑白白白,黑白白黑白白

N(3)=4 黑黑黑白白白,黑黑白黑白白,黑白黑白黑白,黑黑白白黑白白

故14

20:递归式的先序遍历一个n节点,深度为d的二叉树,则需要栈空间的大小为:

A: O(n)

B:O(d)

C:O(logn)

D:(nlogn)

B:三种遍历算法中递归遍历左右子树的顺序都是固定的,只是访问根结点的顺序不同。不管采用哪种遍历算法,每个结点都访问一次且仅访问一次,故时间复杂度都是O(n).在递归遍历中,递归工作栈的栈深恰好为树的深度,所以在最坏的情况下,二叉树是有n个结点且深度为d的单支树,遍历算法的空间复杂度为O(d).

第二部分:多选

21:两个线程运行在双核机器上,每个线程主线程如下,线程1:x=1;r1=y;线程2:y=1;r2=x;

X和y是全局变量,初始为0。以下哪一个是r1和r2的可能值:

A: r1=1,r2=1

B: r1=1,r2=0

C:r1=0,r2=0

D:r1=0,r2=1

ABD:A执行顺序 x=1 y=1 r1=y r2=x B执行顺序y=1 r2=x x=1 r1=y D执行顺序x=1 r1=y y=1 r2=x;

22.关于Linux系统的负载,以下表述正确的是:

A: 通过就绪和运行的进程数来反映

B: 通过TOP命令查看

C: 通过uptime查看

D: Load:2.5,1.3,1.1表示系统的负载压力在逐渐变小

答案,ABC,解释:在Linux中,进程分为三种状态,一种是阻塞的进程blocked process,一种是可运行的进程runnable process,另外就是正在运行的进程running process。系统的load是指正在运行running one和准备好运行runnable one的进程的总数。Load 数字越大负载越高,负载为1表述CPU已经100%功率运行,大于1表示CPU满负荷运行还有额外的等待运行的进程,D说明系统负载变大,load average分别是系统1分钟,5分钟,15分钟的平均负载

23:关于排序算法的以下说法,错误的是:

A: 快速排序的平均时间复杂度O(nlogn),最坏O(N^2)

B:堆排序平均时间复杂度O(nlogn),最坏O(nlogn)

C:冒泡排序平均时间复杂度O(n^2),最坏O(n^2)

D:归并排序的平均时间复杂度O(nlogn),最坏O(n^2)



24:假设函数rand_k会随机返回一个【1,k】之间的随机数(k>=2),并且每个证书出现的概率相等。目前有rand_7,通过调用rand_7()和四则运算符,并适当增加逻辑判断和循环控制逻辑,下列函数可以实现的有:

A:rand_3B:rand_21 C:rand_23D:rand_49

ABCD rand_49=rand_7^2=7*(rand_7-1)+rand_7 .总结:用rand_a构造rand_b,在不限制运算符的情况下,(1)a>b时一定可以用rand_a构造rand_b,只需判定rand_a()中小于b的数返回;(2)a<b时,则需要先构造rand_a^2=a*(rand_a-1)+rand_a,直到a^2>b,这样使用(1)的方法即可。见我的博客:http://blog.csdn.net/zhuqiuhui/article/details/39611781

填空和问答

25.某二叉树的前序遍历-+a*b-cd/ef,后续遍历abcd-*+ef/-,问其中序遍历序列为:__________a+b*c-d-e/f _________________________________________

我的解析:如下图,再进行中序遍历即可



26.某缓存系统采用LRU,缓存容量为4,并且初始为空,那么在顺序访问以下数据项的时候:1,5,1,3,5,2,4,1,2出现缓存直接命中的次数为:(3),最后缓存即将淘汰的是(5)

我的解析:LRU:Least Recently Used近期最少使用算法



27.两个较长的单链表a和b,为了找出节点node满足node in a并且node in b。请设计空间使用尽量小的算法。

(1)如果相交的话可以得出空间复杂度O(1),时间复杂度O(m+n)的算法:求得链表长度length_a和length_b,假设链表a比较长,则a链表指针先走(length_a-length_b)的步长,随后两链表指针同步向后遍历,当出现结点相等的接点就是相交点。

1. #include <iostream>

2. using namespace std ;

3. struct node

4. {

5. int v;

6. node *next;

7. };

8.

9. /* 返回链表的长度 链表为空 返回0

10. */

11.

12. size_t listLen(node * p)

13. {

14. size_t num = 0;

15. while (p!=NULL)

16. {

17. num++;

18. p = p->next;

19. }

20. return num;

21. }

22.

23. // 如果找到了 则返回指针 指向公共节点

24. // 如果不存在 则返回空指针

25.

26. node * findFirstCommenNode(node * pheada, node * pheadb)

27. {

28. size_t lenA = listLen(pheada);

29. size_t lenB = listLen(pheadb);

30.

31. node * plistA = pheada;

32. node * plistB = pheadb;

33.

34. //调整长度

35. //plistA 指向较长的一个

36. if (lenA < lenB)

37. {

38. plistB = pheada;

39. plistA = pheadb;

40.

41. size_t t = lenA;

42. lenA = lenB;

43. lenB = t;

44. }

45.

46. while(lenA > lenB)

47. {

48. plistA = plistA->next;

49. --lenA;

50. }

51.

52. //一样长了

53. //寻找公共节点

54.

55. while (plistA!=NULL && plistA != plistB)

56. {

57. plistA = plistA->next;

58. plistB = plistB->next;

59. }

60.

61. return plistA;

62. }

(2)如果两个链表不是相交问题,那么就只能采用蛮力法了O(m*n) 。

28.存储数据量超出单节点数据管理能力的时候,可以采用的办法有数据库sharding的解决方案,也就是按照一定的规律把数据分散存储在多个数据管理节点N中(节点编号为0,1,2,,,,N-1)。假设存储的数据时a 请完成为数据a计算存储节点的程序。

[cpp] view plaincopy

1. #define N 5

2.

3. int hash(int element){

4.

5. return element*2654435761;

6.

7. }

8.

9. int shardingIndex(int a){

10.

11. int p = hash(a);

12.

13. _________________________; //这里是空格

14.

15. return p;

16.

17. }

解答:需要最P做处理,使hash值映射到(0,1,2,,,,N-1), p=p%N。

29、宿舍内5个同学一起玩对战游戏。每场比赛有一些人作为红方,另一些人作为蓝方。请问至少需要多少场比赛,才能使任意两个人之间有一场红方对蓝方和蓝方对红方的比赛?

分析:这题正确答案应该是4,如果用推导的方法获得递推公式



简化为



所以T(5)=T(3)+2=T(2)+4=T(1)+6,T(1)=0; T(5)=6;

但实际上我们可以举出只需要四场比赛的例子。

第一场: 红方为ABE,蓝方为CD

第二场:红方为CDE,蓝方为AB

第三场:红方为AC,蓝方为BDE

第四场:红方为BD,蓝方为ACE

30、一个有10亿条记录的文本文件,已按照关键字排好序存储。请设计算法,可以快速的从文件中查找指字关键字的记录

分析:有10亿条记录的文本文件存储在磁盘中,不能一次存入内存,所以讲10亿条分为N份,然后顺序将第N份存入内存,对关键字进行哈希得到ID号,然后进行二分法比较,如果不在这一份之中,那么需要将磁盘中的第二份导入内存,就这样进行计算~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: