本文主要是讲述我参加阿里巴巴2013年校招的经历,感谢并发编程网博主的推荐。
电面
说是电话面试,其实和正常面试感觉没啥区别,也是聊,也是写代码。 用的是这个工具,http://codassium.com/ ,双方写东西,对方都能看到。面试最开始普遍都是让自我介绍,这是吹牛的良好机会,主要内容为:看了哪些牛逼的书,认识哪些牛逼的人,做了哪些牛逼的事。然后就到了问问题的阶段。
问题1.主要是根据做所项目,由于之前做了一个操作系统的模型,所以问了一下进程间调度和通信是如何实现的。又问了一下linux下进程间通信都有哪些方式。
回答大概说调度是基于进程控制块(PCB),我简单做了一个时间片轮转的调度。通信也做的很简单。进程间通信的方式大概是管道(命名、匿名),消息队列,信号,共享内存和socket,只说了这几个。
问题2.在那个网页上,面试官写了一个结构体,大概像下面这样:
struct st{
int a:1;
int b;
char c;
int d;
};
问,sizeof(st)会是多少。
这个明显就是结构体对齐问题,但是我答的并不好,因为时间久了有点忘记怎么算了。还有第二行那个位域的知识,之前我也没有见到过,所以这个问题答的并不好。然后面试官又问结构体对齐和哪个硬件有关,我说不是内存就是CPU,然后面试官很nice的给我讲为什么和CPU有关。其实面试官还是很nice的。
问题3.写一个二分查找。这个很简单,然后就写了一下,然后其中有一句,int mid = (l + u) /2; 。面试官问,如果溢出怎么办,我说分开除,特判两个都是奇数这种情况,面试官说要求不用判断。于是我想了一下,写出了这样
int mid = l/2 + u/2 + ((l&1)&&(u&1)); 想法很简单,如果两个数都是奇数,则最终值+1 。面试官觉得我这个写法太难看了,于是又耐心的教导我,如何写更好看,用的是减法然后右移。
问题4.让写一个快速幂,很快写了出来,然后紧接着又问快速幂取模,之前没有想过,所以卡死了。然后面试官说,离散数学里面有讲,可能你忘记了(这句话让我很感动啊),说你找时间去看看吧。
问题5.让实现两个方法,一个插入一个查找,数据是一个个的字符串。数据结构自选,我一看机会来了,就从线性表(数组和链表)开始说起,然后谈树,从最简单的查找树又讲到红黑树,然后又开始说哈希,大谈哈希和红黑树各自的优缺点。然后面试官说:你不用和我说这么多,我就让你实现两个方法。我说那我实现一下哈希吧,然后就开始写代码,代码大概是这个样子的:
int hash(char * str)//把字符串映射为一个数字
{
int ans = 0;
while(*str != ''){
ans = (ans * 31 + *str) % SIZE;//哈希桶的数目为SIZE
}
return ans;
}
bool insert(char* str)
{
int idx = hash(str);//table表示一个已经初始化好的桶
while(table[idx] && idx < SIZE){//如果当前位置已经存,向高位去探测
++idx;
}
if(idx == SIZE)//表示越界,插入失败
return false;
else {
table[idx]=str;
return ture;
}
}
其实是个非常非常简单的哈希,然后面试官问,这样如果数据数量超过了桶的大小,那一定会出错的,有啥不出错的办法呢,我说这个table里面一个元素只能存一个值,但是如果我存的是链表的头结点,就可以存多个值了。时间好像到了,然后面试官也没有继续让我写,就说就这些问题了,然后就让我问他问题,我请教了一下在阿里大概生活什么状态,然后就愉快的结束了此次面试。
这次面试后,由于一些阴差阳错,和通知我这次面试过了的人总是没能联系上,后来终于联系上了,然后被告知等消息,后来得到了去阿里面试的消息。并且被通知的是终面,高高兴兴去了。
进一小屋,见到面试官,面试官看了眼简历“你没有笔试卷子?”“你之前也没面试记录?”,然后在我简历上大笔一挥写下“建议先XXXX(没看到)”,然后就说,你出去等着吧。遂从终面,降级为从头开始面。
真人面试第一场
我还没有搞清楚状况,就被另一个面试官带到一个很多对面试官和应聘者的小屋。面试官开始看简历,然后问问题。
问题1.两个字符串,把第二个串中出现的字母从第一个串中去掉。例如,a: Hello world b:el 最终为:Ho word。要求空间复杂度为O(1)。
最初理解错题意了,我以为是完全匹配才去掉,然后写了半天,写完了给面试官看的时候,被告知搞错了,遂重写,想法就是把b串映射到一个table里面,然后第一个串挨个字符判断有没有,有的话就去掉。实现上很多需要注意的地方,最终的要求是只扫一遍a字符串就把结果给出来,写着写着也写出来了。
问题2.谈项目,依旧是问,进程调度和通信如何做的,内存管理如何做的,支持哪些接口,如何实现的。然后我就说自己只是实现了最简单的功能巴拉巴拉,面试官问,那你的内存管理如何优化呢?我又巴拉巴拉说了一些。然后又被问到SQLite某个接口内部是如何调用,如何实现的(因为简历上有写做过分析SQLite的项目)。但是当时做的并不细致,这个问题没有答上。
问题3.问a[5][5] 和 **p=a a[2][3]和p[2][3]指向的是同一个位置吗?我答不是,然后问为什么,我是瞎猜的当然不知道为什么了,然后面试官又很nice的引导我,让我尽量自己去给出答案。面试官真心赞!
问题4.问了一个C++的多态是如何实现的,在我答出虚表之后,又问基类的虚表是什么样的,派生类虚表是什么样的。对于C++了解的真心不多,于是瞎猜也不知道猜的对不对,然后面试官说既然问到这里又问我一道关于继承的问题,不过我不会。面试官很nice的说“没事,每个人的知识结构都不同,不可能全都覆盖嘛”。
面试结束时,我问的内存泄漏都可能有哪些情况,然后被告知情况太多了,要靠经验来了,这也是为什么高手之所以值钱的地方。于是就继续去等下一次面试了。
真人面试第二场
感觉这次也是一面,因为还是在一个很多面试官和应聘者的屋子里,第二位面试官不知道为什么,很多时候我说完了他都不说话,在那想。开场的时候他很热情的自我介绍了一下,然后就开始面试。
问题1.“随便写一段代码吧,短点的”,于是我就把上面写过的hash函数写了,问我为啥写这个,我说因为之前电面的时候写过,联想就写了。现在后悔啊,我写strcpy多好,还漂亮,还短。
问题2.问我++a和a++有啥区别,我说一个创建了副本,++a更快速一些,他问你测过效果吗?我又说,其实在这里面时间是一样的,因为编译器给做优化了。他又说,那这个技巧就没用了呗,我说不是,当a是一个结构很大的类的时候,创建一个副本开销是很大的,还是很有用处的。
问题3.从哈希聊啊聊聊到了红黑树,让讲讲红黑树,然后又给他说了一下红黑树。
问题4.看我简历上写了在某项目中实现8种排序算法,于是让我介绍一下排序算法各自的优缺点。于是我从快排讲起,然后讲快排的优化,讲插入排,讲堆排,最后又说STL中sort的实现方式(快排+堆排),又提了一嘴计数排。
问题5.看我之前没有做过笔试题,让我做笔试题最后几道大题中的两道,第一道:在一个数组中找到min和max,要求比较次数越小越好,说了一个比较次数是1.5n次的。第二道:求三个升序数组a[l],b[m],c[n]中,每个数组出一个数,要求max(|a[i]-b[j]|,|a[i]-c[k]|,|b[j]-c[k]|)最小。我想了一下给出了一个l*(log(m)+log(n))的,用二分查找在后两个数组找离的最近的,然后去比较。被问还有什么别的想法,后来又提示归并排序,最终给出了用归并的想法,O(l+m+n),个人感觉,这个想法有的时候真的未必比我第一次给出的二分的效率高,比如当m,n特大,l特小的情况下。
问题6.问static关键字你都一般怎么用,我说修饰函数和变量。然后又问const关键字,判断是内容不变还是指针不变,这个之前看C++primer里面有讲。然后又问知不知道volatile,我说见过,查过,但是没用过。
问题7.又是聊项目,还问为什么投的是杭州的。
基本面到这里就结束了,让我继续等着。
这时已经12点多了,阿里管午饭,和两个小伙伴一起吃的。
真人面试第三场
第三场的场地明显就高端大气上档次了很多,虽然也有几对面试官和应聘者。以让我自我介绍开场。
自我介绍之后,他明显对我说的东西没啥兴趣(确实是有点假大空),然后聊实习经历(唯一的一个聊实习经历的面试官)由于实习干的工作确实都很弱,也没啥好说的,显得自己很低端。然后又开始聊项目,依旧是之前问过的问题,都差不多。然后问我对哪些技术感兴趣,我说网络编程,还有NoSQL,比如redis,mongoDB这些。果断被问到这些内容,我只是感兴趣,打算下一步开始学习,当然不会啊,只能说不会了。聊的差不多了,问了两道题,可能是三面已经是下午了,我开始犯困,脑子开始不灵了。
问题1.进程线程区别。答是否拥有资源,一个进程可多个线程,开进程消耗资源比开线程多等常规答案。问,还有吗?看我答不出来了,又问开进程和线程分别都需要什么资源,答进程需要开独立的内存空间,线程不知。
问题2.给一个旋转有序的数组,所谓旋转有序,比如1,2,3,4,5算。4,5,6,1,2,3也算。在这个数组中查找元素p,返回bool是否找到。让写代码,接口给定义好。这个问题也算不上难,用二分的想法很容易就写出来了,然后他看了半天我的代码,应该是没啥问题,然后开始下一道。
问题3.给定一个矩阵,里面是‘#’或‘.’,一个表示可以走,一个表示不可走,给定初始的位置bx,by。给定结束的位置ex,ey。还有个梯子,梯子长度为N,用梯子可上走可下走。判断是否可走到。一看,简单深搜广搜都能做的简单题,遂开始吹牛,说这题简单,用深搜广搜都行神马的。被问深搜广搜区别,秒答之,广搜能找到最短路径,但是费点空间。遂题目升级为求出最短路径,用广搜。然后就是我悲剧的开始。这个题真心简单,只不过一年多没有写广搜的代码了,也可能是累了,当然最可能的就是自己太弱了。写的奇慢,干写不出东西,我自己都不太理解,想法很清楚,为啥写的这么慢。而且还有各种错误,各种被找出来。最终死在了一个天大的BUG上,忘记标记走过的路了。肯定会爆内存啊。这要是机器写,一运行就看出来了,可是手写就都要自己想清楚,要不然就跪了。
在指出这个BUG之后,面试官说,那我这里没什么问题问你了,你有什么问题吗?我又把内存泄漏原因这个问题问了一遍,答案和上一次问差不多。从面试官的态度,我知道自己跪了。他然后严峻的说“那你回去吧,带好东西”。我出去逛了一圈,想要留一下他的名片,于是又走回去要了一下名片。他说没带名片而且公司好像也…我就懂了,然后他坚定的伸出了胳膊指向门口,看着他皱着的眉头,我知道,必跪无疑了。又深深的后悔自己这个SB行径。
面试,真的靠缘分,要看面试官和自己是不是有眼缘,要看面试官的知识结构和自己是否交叉的地方很多。不管怎么说,一次独特的人生体验吧,感谢阿里花这么大成本(前后4次面试)来面我,虽然最后悲剧的概率极高,不过从这几次面试中还是能看到自己很多问题的,也学到了不少知识。当然更是认清了自己弱菜本质。
还有一个同去的小伙伴,明确的被告知回去等offer~在这里恭喜他啦!
对自己说:加油,奋力前行!