随着各大公司春招的开始,很多小伙伴都行动起来了,我有幸能够加入百度并和大家分享自己的经验心得。由于我面试的都是比较大的公司,所以自然也是做了这方面的准备,因此这篇总结并不一定适合想去创业公司的同学。另外,由于经验本来就是主观性极强的东西,加之笔者水平有限,所以如果有不认可的地方,万望诸君呵呵一笑,抛之脑后。
接下来,我就斗胆分享一下自己在准备和参加面试的过程中的收获、对面试的思考,以及一些可能对大家有用的建议。最后附赠一份大礼包,希望能帮助每位读者找到自己心仪的工作。
有些人可能会把面试看的太重,觉得面试过了就能进入大厂,技术和财富兼得……
我倒是觉得,面试没有这么夸张,它其实是一次你和面试官互相了解的绝佳机会,借此机会你还可以对未来的工作有初步的了解和现在行业的情况。
面试本身并不能完全评价一个人的实力。面试通过的人,也许只是恰好在面试时遇到了自己熟悉的问题,面试不通过,也有可能是面试官自身的问题,并非每个面试官都具备客观评价别人的能力。
换句话说,面试没通过也许是面试官没有发现你的才华,面试通过了也并不代表你就能胜任工作,因为进入企业之后可不是每天负责回答面试题!
所以从这一点来看,面试有点像相亲。你满意我,我满意你,王八对绿豆——看上眼了,那就一拍即合,否则就分道扬镳。我本人非常希望能够多几轮面试(实际并不总是能做到),这样大家都有充足的时间互相了解,决定去留。
网上某些面经中,介绍了一些“装逼”的方法,还有所谓的“面试技巧”,我是不太认可的。技巧需要有,这是为了让你更好的展示自己,而非坑蒙拐骗,无理取闹,无中生有。我更想展现一个真实的自己,如果面试官不认可,说明我们没有缘分,或者说自己的能力还不够。
不知道有多少读者和我一样有过这样的困扰:“我知道某些东西很重要,所以去百度查了资料,但是查到的文章质量很差,正确率没有保证”。这其实是正常的,优秀的文章一般都放在优秀的作者的个人博客上,这恰恰是搜索引擎的盲区,所以一般只能搜到 CSDN、博客园这种地方的文章。自然就无法保证文章质量。
出于这种考虑,我在文章最后的复习资料中,提供了用于学习相关基础知识的书籍,如果您恰好是 iOS 开发者,还可以阅读我收集的一些高质量文章,正确性比较有保证。
除了准备通用的基础知识以外,简历也是一个很重要的环节。一直很仰慕唐巧老师的猿题库,无奈简历太差,都没有收到面试邀请。后来好好改了简历以后,就没有这种问题了。关于简历的书写,推荐篇文章:iOS - 一份参考简历,请注意查收!,没有亮点,就当是抛砖引玉。
最后,当然是准备好相关岗位的基础知识了。作为 iOS 开发者,虽然 Swift 已经发布好多年了,但是大公司转向 Swift 的动作还不明显,所以 Objective-C 几乎是必备项,Swift 只能能算是加分项。iOS 方面的知识也必不可少,虽然招聘信息上写着如果基础扎实,零 iOS 基础也可以,但是现实往往是比较残酷的。
扯了这么多,终于进入正题了,分享一下我的面试经历。题目如下,破折线后面是简单的解决思路。
MVC
具有什么样的优势,各个模块之间怎么通信,比如点击 Button 后 怎么通知 Model?UITableView
的相关优化KVO
、Notification
、delegate
各自的优缺点,效率还有使用场景KVO
copy
方法SEL
和 IMP
的区别autoreleasepool
的使用场景和原理RunLoop
的实现原理和数据结构,什么时候会用到block
为什么会有循环引用GCD
如何实现这个需求:A、B、C 三个任务并发,完成后执行任务 D。NSOperation
和 GCD
的区别CoreData
的使用,如何处理多线程问题cell
是否显示在屏幕上TCP
与 UDP
区别TCP
流量控制UIView
生命周期viewDidDisappear
方法和 B 的 viewDidAppear
方法哪个先调用?block
循环引用问题ARC
的本质RunLoop
的基本概念,它是怎么休眠的?Autoreleasepool
什么时候释放,在什么场景下使用?首先是四个算法题:
partion
函数的原理,堆排(不稳定),归并排序,基数排序。最后是 iOS 相关,面试官问的很开放,都是谈谈自己的理解:
load
方法和 initialize
方法的异同。——主要说一下执行时间,各自用途,没实现子类的方法会不会调用父类的?一面的问题一般比较基础,主要是算法和 Objective-C
看运气 有些面试官会在问一遍一面的问题
首先是给一个小时,手写算法两个算法题。接下来问了 TCP 握手相关的。最后问了 OC 的一些细节问题。
主要是计算机方面的大杂烩,涉及操作系统,网络,移动开发,算法等。难度不大,目测是为了淘汰浑水摸鱼的人,就不列出题目了,算法有三题,直接在线写:
[5,5,10,2,3]
一共有四个子数组的和是 15,比如 [5,10]
,[5,10]
,[10,2,3]
,[5,5,2,3]
。这个就是简单的递归了,分两种情况,当前位置的数字在子数组中,以及不在子数组中。全部是 iOS 题,可能是觉得算法已经面过了:
NSString *s2 = s1; s2 = nil
这样的语句,可能就不会有 retain
和 release
方法了。bind
函数了解过么,果断说已经忘了本来以为面的这么差肯定是挂了,没想到还是过了一面。过了不到一个小时,HR 电话打过来,约了两天后二面。
纯数学和算法:
`c int main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1);
printf(“%d,%d”,*(a+1),*(ptr-1)); }`
答案是 2 和 5。a
是指向数组开头元素的指针,a + 1
就是指向下一个元素的指针,所以星号求值以后是 2。&a
相当于是数组的指针,&a + 1
是数组后面一个数组的指针,然后转换成int *
类型是 5 这个数字后面的一个数字的指针。再减一就是指向 5 的指针,所以星号求值以后是 5。
某个地方天气有如下规律:如果第一天和第二天都不下雨,则第三天下雨的概率为30%;如果第一天和第二天中有任 意一天下雨,则第三天下雨的概率为60%。问如果周一周二都没下雨,那么周四下雨的概率为*_*。
简单的概率题,答案是:30% * 60% + 70% * 30% = 39%
某痴迷扑克的小团体喜欢用23456789TJQKA来计数,A后面是22,23,…,2A,32,…,AA,222,… 依次类推。
请用C/C++或Java写个程序,将用字符串表示这种计数法转换成字符串表示的10进制整数。其中,该计数法的2就对应于十进制的2,之后依次递增。C/C++函数接口: char* pokToDec(char *)
我的解决思路是进制转换,类似于 16 进制转换 10 进制这种,最后再把数字转成 char *
类型。
面试官可能会问到你闻所未闻的算法,这时候你不应该自己瞎想,而是先和面试官把问题讨论清楚。要知道,通过沟通弄明白复杂的问题也是一种能力,在和面试官交流的过程中,不仅仅可以搞清楚题目真正的意思是什么,还可以展现自己良好的交流沟通能力。所以千万不要因为紧张或者害羞而浪费这次大好的机会。
有些题目似曾相识,但是暂时没有思路。这时候不妨告诉面试官,给我一些时间思考这个题。然后不要急,不要慌,就当他不存在,拿出纸和笔慢慢算(这充分说明了面试戴耳机的重要性)。你一定要坚定一个信念:“任何一道稍微有难度的算法题,除非做过,否则一定是需要时间想的”。所以,合理的安排思考时间吧。如果十几分钟都想不出来,可以直接放弃。
有时候面试官会要求在线编程,相信我,他不会无聊到盯着你的代码看的,面试官一般都很忙,他也有自己的工作要完成,所以你就当是用自己的 IDE 就好。在线编程往往是一个中等难度的问题,所以不要自己吓唬自己。同时要注意代码格式的规范,适当的注释,提前编写好测试用例等,即使没有解决问题,也至少要把自己良好的编程习惯展示给面试官。
这个问题有可能是面试官故意说得含糊不清,考察你的交流能力,也有可能是无意的,或者是你的理解方式出现了偏差。不管是以上哪种问题,你都应该先和面试官交流,直到你搞懂了面试官要问你什么,而不是按照自己的理解说了一堆无用的东西。
举个例子,面试官可能会问了一道算法题:“如何判断两个无限长度的链表是否有交点?”。对于“无限长度”可以有不同的理解,如果真的是有无穷多个节点,那显然这个问题是无法解决的。但如果链表仅仅是有环,那么还是可以解决的。如果面试官的本意是链表有环,但你错误的理解成了无穷多个节点,那么必然会导致无法回答这个问题。而且这并非能力不足,而是属于交流沟通方面的失误,这也正是我想分享的“技巧”。
还有一些问题,虽然你没有接触过,但是由于对类似的问题或者情况有过思考,所以可以合理假设。比如面试官问 “ARC 会对代码做什么样的优化?”。我们知道 ARC 的本质就是在合适的地方插入 retain
和 release
等方法,那么就应该从这个角度出发去思考问题。
显然分别执行 retain
和 release
操作是没有必要的,那么就可以构造出相应的例子:
NSString *s1 = @"hello";
NSString *s2 = s1;
NSString *s2 = nil;
由于这种问题我们没有真正实践过,所以可以委婉的告诉面试官:“根据我的推理,可能会有……”。
遇到不会的问题果断承认啊。如果是基本问题,比如问你哈希表怎么实现,你说不会,那么这次面试可能就悬了。如果是有一定难度的问题,那么你承认不会,也是一种明智之举,毕竟人无完人,一个问题不会并不能全盘否定一个人的能力。
但是比较糟糕的一种情况是,面试者由于过分紧张,担心答不上面试官的问题会有严重后果,所以尝试着去敷衍面试官。比如:“我猜是 xxx 吧”,“我觉得可能是 ……”,更有甚者直接装逼:“这个我试过,不就是 xxx 么”。要知道,此时的你,由于紧张,在心态上已经输给了面试官,更何况面试官问你的问题一定是他有把握的,你觉得这时候你负隅顽抗会有几成胜算呢?
所以,面试官问我“堆排序”的细节时,由于我当时忘了堆排序是怎么实现的,所以我直接告诉他我记不清了。另一个主动认输的例子是面试官问我 RAC 如何实现双向绑定,我告诉他这个是我当时学习的时候写过的 demo,因为不常用,已经只记得一些简单的概念了。
最后,还需要保持一个平稳的心态:“面试时尽力就好,遇到自己不会的问题也是正常情况”。如果面试者顺利答对了所有问题,难免会让面试官感到一丝尴尬,面试者也有可能会产生一些别的情绪。所以,我们要做的只是把自己的能力展示给面试官,做到不骄不躁。
除了能够回答上面试官的问题以外,我建议自己准备一两个杀手锏级别的话题。所谓的杀手锏,至少具备以下几个特征:
以 iOS 中的 UITableView
的调优为例,我自认为对它有一定的理解,同为 iOS 开发者的读者可以阅读这篇文章:
iOS性能优化
优雅的处理 iOS 中复杂的 Table Views
启动优化,让你的App有顺滑无比的启动速度
这一类的话题通常需要仔细研究官方文档,iOS 开发者还可以观看 WWDC 视频,然后花上充足的时间去总结。
iOS音视频技术合集
由于此类话题数量不多,所以准备一个或数个即可,面试时可以有意识的将面试官引导到这些话题上去,从而充分的展示自己。
通常情况下,面试结果都会在 1 - 3 天内知道。有的面试官会当场告诉你通过了,有的公司面试结束后几个小时就能出结果。
但有些时候,由于某些原因(我也不清楚。。。。可能是比较忙?),你迟迟无法获知面试结果。这时候你可以选择耐心等待,获知直接给 HR or 内推者发送邮件。一般来说面试结束后三天还没收到通知,你可以发送邮件询问或者再等等。
对于读到这一段的读者,为了感谢你耐心的听我废话了这么久,送上一波精心整理的干货和资料。不敢说完全没有错,但是应该比自己去查要靠谱得多。主要涉及算法、网络、操作系统、Objective-C 和 iOS 五个方面。如果你不是 iOS 开发者,相信前三部分的资料也或多或少能够帮上你。
这一部分的内容主要分为以下几个部分:字符串、数组与查找、链表、树以及其他基础问题。
总的来说,算法问题可以分为以下三类:
一般来说,一类问题难度不大,面试前简单复习一下,面试时小心仔细,全面思考即可。二三类问题是面试重点,需要提前准备。第四类问题通常出现较少,即使不会做,对最终评价的负面影响也不会有前三类那么大。
如果时间充裕,我建议阅读
动画详解十大经典排序算法(C语言版)
PS: 最近有小伙伴被问到了哈希表的实现。这可以理解为算法,也可以归类为计算机基础知识。总的来说你至少需要明白哈希值的特点和两种解决冲突的方式:拉链式和开放寻址。
根据不同的面试岗位,侧重点略有不同。对 iOS 和 Android 开发者来说,HTTP 考的略少,以 TCP 和 UDP 为主。其实 UDP 基本上只会考察和 TCP 的区别。
当然还有一些常见的基础问题,比如 Cookie 和 Session 的考察,POST 和 GET 的考察,HTTPS 的简单了解等。这些问题在我的博客中都有简单的总结。
以下是我总结的一些问题:
我被问到的操作系统问题很少,所以仅仅总结了一些自认为比较重要的问题。关于这一部分的知识,推荐阅读**《程序员的自我修养》,如果时间有限,你可以阅读我的《程序员的自我修养读书笔记》**,并思考这些问题:
关于多线程相关的,推荐阅读这篇文章
详解RunLoop之源码分析
首先两本必备的神书一定是要读完的。一本是讲 OC 的《Effective Objective-C 2.0》,中文名叫:“编写高质量 iOS 与 OS X 代码的 52 个有效方法”。另一本书叫:《Objective-C 高级编程》。前者讲解 OC 中各种细节,后者主要讲了 ARC、Block 和 GCD。
光是读书,思考不够,很容易在面试时被问懵逼,所以建议一遍尝试回答面试真题,一边阅读以下总结性的文章,重要性不分先后:
强烈推荐第八篇文章,做完这上面的题目基本上可以应付大多数 OC 方面的问题了。
其中需要重点了解 runloop
,它不仅仅是简单的“跑圈”的 概念,很多问题其实都与它有关,
作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS交流群:1012951431 不管你是小白还是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长!
另附上一份各好友收集的大厂面试题,进群可自行下载!