前言
博主明天上午9点还有面试,今天突然看到某大牌IT公司笔试题目,必须做一下了
题目
一、单选题
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的整数
B: h(K)=1;
C: h(K)=K mod N;
D: h(K)=(K+rand(N)) mod N, rand(N)返回0到N-1的整数
选择C,解释:开始纠结于C和D,但是hash的特性在于常数的时间执行插入、删除和查找操作,用D作为hash函数无法满足该条件,用C产生碰撞可以用链接法解决冲突,感谢@
zdw12242的纠正
2.下面排序算法中,初始数据集的排列顺序对算法的性能无影响的是:
A: 堆排序 B:插入排序
C: 冒泡排序 D:快速排序
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:冯诺依曼体系结构的主要特征是存储程序的工作方式
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
A:CPU B: Cache C:RAM D:ROM
B,解释:冯诺依曼体系结构必要组成部分:运算器、控制器、存储器、输入设备、输出设备,Cache属于缓存了
5. 一个栈的入栈序列式ABCDE则不可能的出栈序列是:
A:DECBA B:DCEBA C:ECDBA D:ABCDE
A:DECBA B:DCEBA C:ECDBA D:ABCDE
C,不解释
6.你认为可以完成编写一个C语言编译器的语言是:
A:汇编 B:C语言 C:VB D:以上全可以
A:汇编 B:C语言 C:VB D:以上全可以
D,解释:见知乎的一个解答
http://www.zhihu.com/question/20822934,其实你学好编译原理用什么语言都能写出来
7. 关于C++/JAVA类中的static成员和对象成员的说法正确的是:
A:static成员变量在对象构造时候生成
B: static成员函数在对象成员函数中无法调用
C: 虚成员函数不可能是static成员函数
D: static成员函数不能访问static成员变量
A:static成员变量在对象构造时候生成
B: static成员函数在对象成员函数中无法调用
C: 虚成员函数不可能是static成员函数
D: static成员函数不能访问static成员变量
C,解释:虽然博主主要以php和c为主,php也能面向对象,我来简单说明一下。(1)static成员变量可以直接定义,例如public statci $a = 10; 所以A错(2)在对象成员函数里可以通过类名::static函数名的方法调用,我的项目中超过静态方法(4)同样道理,类名::static成员变量名,这也是访问static成员变量唯一的方法(3)是正确的,虽然我都不知道什么是虚函数,排除法可以完成
9:某进程在运行过程中需要等待从磁盘上读入数据,此时进程的状态将:
A: 从就绪变为运行 B:从运行变为就绪
C: 从运行变为阻塞 D:从阻塞变为就绪
A: 从就绪变为运行 B:从运行变为就绪
C: 从运行变为阻塞 D:从阻塞变为就绪
C,解释:I/O事件让进程从running->waitting,参考链接:
http://blog.csdn.net/wzy_1988/article/details/11003521
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!)
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,解释:没啥好解释的
11: n从1开始,每个操作可以选择对n加1或者对n加倍。若想获得整数2013,最少需要多少个操作。
A:18 B:24 C:21 D;不可能
A:18 B:24 C:21 D;不可能
A,解释:
数学方法->从 2013 倒推, 奇数 减一,偶数 除2,
编程实现->是一个明显的bfs题目,编程实现为18,共享一下自己的bfs代码:
#include <stdio.h>
#include <stdlib.h>
#define FINAL 2013
#define MAX 25
typedef struct num {
int d, time;
} num;
typedef struct queue {
int front, rear, count;
num data[10000000];
} queue;
void enQueue(queue *q, num d)
{
q->data[q->rear ++] = d;
q->count ++;
}
num deQueue(queue *q)
{
num res;
res = q->data[q->front ++];
q->count --;
return res;
}
int main(void)
{
int flag = 0;
num bt, one, two, s;
bt.d = 2;
bt.time = 1;
queue *q = (queue *)malloc(sizeof(queue));
q->front = q->rear = q->count = 0;
enQueue(q, bt);
while (q->count > 0) {
s = deQueue(q);
if (s.d == FINAL) {
flag = 1;
printf("%d\n", s.time);
break;
}
one.d = s.d + 1;
one.time = s.time + 1;
if (one.d <= FINAL && one.time <= MAX) {
enQueue(q, one);
}
two.d = s.d * 2;
two.time = s.time + 1;
if (two.d <= FINAL && two.time <= MAX) {
enQueue(q, two);
}
printf("%d\n", q->count);
}
if (flag == 0)
printf("不可能!\n");
return 0;
}
12:对于一个具有n个顶点的无向图,若采用邻接表数据结构表示,则存放表头节点的数组大小为:
A: n B: n+1 C: n-1 D:n+边数
A,解释:感觉没啥好解释的,n个顶点数组大小应该就是n吧,如果非要从下标从1开始,那就是n+1,蛋疼的题目,话说在ACM上写bfs,dfs,最短路径全是用邻接矩阵,就谁会用邻接表这么蛋疼的设计,又不是hash
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
博主读不懂题啊有没有,我想选c
14.如下函数,在32bit系统foo(2^31-3)的值是:
Int foo(int x)
{
Return x&-x;
}
A: 0 B: 1 C:2 D:4
Int foo(int x)
{
Return x&-x;
}
A: 0 B: 1 C:2 D:4
C,解释:我只想说注意运算符优先级,注意^是异或
15.对于顺序存储的线性数组,访问节点和增加节点删除节点的时间复杂度为:
A: O(n),O(n) B:O(n),O(1) C:O(1),O(n) D:O(n),O(n)
A: O(n),O(n) B:O(n),O(1) C:O(1),O(n) D:O(n),O(n)
C,解释:给定下标,访问为O(1),增加和删除节点涉及到移动操作为O(n)
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
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,解释:字节对齐包含了每个变量自身对齐和复杂类型整体对齐。pragma pack参考链接:
http://blog.csdn.net/wzy_1988/article/details/11834881
对于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
17.袋中有红球,黄球,白球各一个,每次任意取一个放回,如此连续3次,则下列事件中概率是8/9的是:
A: 颜色全相同 B:颜色全不相同C:颜色不完全相同 D:颜色无红色
A: 颜色全相同 B:颜色全不相同C:颜色不完全相同 D:颜色无红色
C,解释:(1)颜色全相同:C(1,3) / 27 = 1 / 9(2)颜色全不相同:3 * 2 * 1 / 27 = 2 / 9 (4)颜色无红色: 2 * 2 * 2 / 27 = 8 / 27 (3)颜色不完全相同 = 1 - P(颜色完全相同) = 1 - 1 / 9 = 8 / 9
18.一个洗牌程序的功能是将n张牌的顺序打乱,以下关于洗牌程序的功能定义说法最恰当的是:
A: 每张牌出现在n个位置上的概率相等
B: 每张牌出现在n个位置上的概率独立
C: 任何连续位置上的两张牌的内容独立
D: n张牌的任何两个不同排列出现的概率相等
A: 每张牌出现在n个位置上的概率相等
B: 每张牌出现在n个位置上的概率独立
C: 任何连续位置上的两张牌的内容独立
D: n张牌的任何两个不同排列出现的概率相等
D,解释:乐乐说选D,其实我觉得A也挺对的,这到题目我写了一个测试洗牌的程序,但是自己测试问题很大,怀疑是随机数获取的问题,求大家帮忙指点:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 10
int arr[N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
void shuffleArray()
{
int i, loc, tmp;
time_t t;
srand((unsigned int)time(&t));
// 洗牌算法
for (i = 0; i < N; i ++) {
loc = rand() % (i + 1);
tmp = arr[loc];
arr[loc] = arr[i];
arr[i] = tmp;
}
// 打印输出
for (i = 0; i < N; i ++)
printf("%d ", arr[i]);
printf("\n");
}
int main(void)
{
int i, n;
while (scanf("%d", &n) != EOF) {
for (i = 0; i < n; i ++) {
// 测试洗牌
shuffleArray();
}
}
return 0;
}
19.用两种颜色去染排成一个圈的6个棋子,如果通过旋转得到则只算一种,一共有多少种染色:
A: 10 B:11 C:14: D:15
A: 10 B:11 C:14: D:15
不会,这么多概率题目啊,我去
20.递归式的先序遍历一个n节点,深度为d的二叉树,则需要栈空间的大小为:
A: O(n) B:O(d) C:O(logn) D:(nlogn)
A: O(n) B:O(d) C:O(logn) D:(nlogn)
B,解释:需要考虑最坏的情况,A和B我不确定啊,蛋疼
二、多选题
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
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,解释:r1和r2不可能同时为0,当一个有赋值时,必然完成了对另一个x或y的赋值
22.关于Linux系统的负载,以下表述正确的是:
A: 通过就绪和运行的进程数来反映
B: 通过TOP命令查看
C: 通过uptime查看
D: Load:2.5,1.3,1.1表示系统的负载压力在逐渐变小
A: 通过就绪和运行的进程数来反映
B: 通过TOP命令查看
C: 通过uptime查看
D: Load:2.5,1.3,1.1表示系统的负载压力在逐渐变小
BC,解释:ALINUX系统还需要包含处于waitting状态的进程 D说明系统负载变大,load average分别是系统1分钟,5分钟,15分钟的平均负载 参考链接:(1)
http://hi.baidu.com/liheng_2009/item/20ddc822dee757192a0f1ca4(2)
http://blog.csdn.net/wzy_1988/article/details/11849473
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)
A: 快速排序的平均时间复杂度O(nlogn),最坏O(N^2)
B:堆排序平均时间复杂度O(nlogn),最坏O(nlogn)
C:冒泡排序平均时间复杂度O(n^2),最坏O(n^2)
D:归并排序的平均时间复杂度O(nlogn),最坏O(n^2)
D,解释:归并排序最坏的时间复杂度也是O(nlogn)
24.假设函数rand_k会随机返回一个【1,k】之间的随机数(k>=2),并且每个证书出现的概率相等。目前有rand_7,通过调用rand_7()和四则运算符,并适当增加逻辑判断和循环控制逻辑,下列函数可以实现的有:
A:rand_3 B:rand_21 C:rand_23 D:rand_49
A:rand_3 B:rand_21 C:rand_23 D:rand_49
ABCD,解释: 参考链接:
http://blog.csdn.net/wzy_1988/article/details/11866973
填空和问答
25.某二叉树的前序遍历-+a*b-cd/ef,后续遍历abcd-*+ef/-,问其中序遍历序列为
扯淡啊,根据前序和后序没法唯一确定中序好不好,我擦
26.某缓存系统采用LRU,缓存容量为4,并且初始为空,那么在顺序访问以下数据项的时候:1,5,1,3,5,2,4,1,2
出现缓存直接命中的次数为:(),最后缓存即将淘汰的是()
出现缓存直接命中的次数为:(),最后缓存即将淘汰的是()
27.两个较长的单链表a和b,为了找出节点node满足node in a并且node in b。请设计空间使用尽量小的算法
求两个链表的公共节点题目
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list {
int value;
struct list *next;
} list;
void addDataInList(list **root, int data)
{
list *pre, *current, *new;
current = *root;
pre = NULL;
while (current != NULL) {
pre = current;
current = current->next;
}
new = (list *)malloc(sizeof(list));
new->value = data;
new->next = NULL;
if (pre == NULL) { // 头节点
*root = new;
} else {
pre->next = new;
}
}
void searchInList(list *first, int m, list *second, int n)
{
int i;
// 构成Y的形状
if (m > n) {
for (i = 0; i < m - n; i ++)
first = first->next;
} else {
for (i = 0; i < n - m; i ++)
second = second->next;
}
// 查找第一个公共节点
while (first != NULL && second != NULL && first->value != second->value) {
first = first->next;
second = second->next;
}
if (first == NULL && second == NULL)
printf("My God\n");
else
printf("%d\n", first->value);
}
int main(void)
{
int i, n, m, data;
list *first, *second;
while (scanf("%d %d", &m, &n) != EOF) {
// 构造第一个链表
for (i = 0, first = NULL; i < m; i ++) {
scanf("%d", &data);
addDataInList(&first, data);
}
// 构造第二个链表
for (i = 0, second = NULL; i < n; i ++) {
scanf("%d", &data);
addDataInList(&second, data);
}
// 第一个公共节点
searchInList(first, m, second, n);
}
return 0;
}
28.存储数据量超出单节点数据管理能力的时候,可以采用的办法有数据库sharding的解决方案,也就是按照一定的规律把数据分散存储在多个数据管理节点N中(节点编号为0,1,2,,,,N-1)。假设存储的数据时a 请完成为数据a计算存储节点的程序
#define N 5
int hash(int element){
return element*2654435761;
}
int shardingIndex(int a){
int p = hash(a);
_________________________; //这里是空格
return p;
}
p = p % N;解释:感觉没啥好解释的,基本的散列函数
29.宿舍内5个同学一起玩对战游戏,每场比赛有一些人作为红方,一些人作为蓝方,请问至少需要多少场比赛,才能使得任意两个人之间有一场红方对蓝方和蓝方对红方的比赛
4,被n多人指点之后的结果
后记
一面创新工厂感觉还不错,期待后续继续给力吧,话说一面结束没消息是闹哪样,先去吃饭,回来继续更新,昨天太累,今天竟然睡到下午才起床