【海归人才网】一个iOS程序员的BAT面试全记录(内含百度+网易+阿里面试真题)作为iOS开发者,虽然Swift已经发布了快两年,但是大公司转向Swift的动作还不明显,所以Objective-C几乎是必备项,Swift都不一定能算是加分项。iOS方面的知识也必不可少,虽然招聘信息上写着如果基础扎实,零iOS基础也可以,但是现实往往是比较残酷的。我的面试经历分享一下我的面试经历,题目如下,破折线后面是简单的解决思路。百度一面:约1.5小时首先是四个算法题:1.不用临时变量怎么实现swap(a,b)——用加法或者异或都可以2.二维有序数组查找数字——剑指offer第3题3.亿级日志中,查找登陆次数最多的十个用户——(不确定对不对,我的思路是)先用哈希表保存登陆次数和ID,然后用红黑树保存最大的十个数。剑指offer第30题4.简述排序算法——快排,partion函数的原理,堆排(不稳定),归并排序,基数排序。然后有一个智力题,没完整的答出来,好像影响不是很大。最后是iOS相关,面试官问的很开放,都是谈谈自己的理解:1.说说你对OC中load方法和initialize方法的异同。——主要说一下执行时间,各自用途,没实现子类的方法会不会调用父类的?2.说说你对block的理解。——三种block,栈上的自动复制到堆上,block的属性修饰符是copy,循环引用的原理和解决方案。3.说说你对runtime的理解。——主要是方法调用时如何查找缓存,如何找到方法,找不到方法时怎么转发,对象的内存布局。4.说说你对MVC和MVVM的理解。——MVC的C太臃肿,可以和V合并,变成MVVM中的V,而VM用来将M转化成V能用的数据。5.说说UITableView的调优。——一方面是通过instruments检查影响性能的地方,另一方面是估算高度并在runloop空闲时缓存。6.谈谈你对ARC的理解。ARC是编译器完成的,依靠引用计数,谈谈几个属性修饰符的内存管理策略,什么情况下会内存泄露。一面的问题非常基础,主要是算法和Objective-C,因为准备比较充分,基本上答出来80%吧。大约一周后突然二面。二面:约0.5小时二面比较突然,先是简单的自我介绍,然后问了三个问题:1.野指针是什么,iOS开发中什么情况下会有野指针?——野指针是不为nil,但是指向已经被释放的内存的指针,不知道什么时候会有,如果有知道的读者还望提醒。2.介绍block。——(接第一问)我让面试官提示我一下什么时候会有野指针,他说用block时,我表示还是不知道,只知道block会有循环引用。于是就扯回了一面的问题。3.说说你是怎么优化UITableView的。——还是一面的问题。三面:北京onsite,约2.5小时首先是给一个小时,手写算法:1.给一个字符串,如何判断它是否是合法的IP地址,比如“192.168.1.1”就是合法的。2.说说大数相加的思路,动手写代码实现。没能写完,主要是大数相加的时候需要考虑负数,耽搁了一点时间。然后让我简述TCP建立和关闭连接时,握手的过程。还问了前者为什么是三次,后者需要四次?接下来是设计了一个实际场景,为了简化问题,我们考虑这个问题:假设有10W条电话号码,如何通过输入电话号码的某一段内容,快速搜索出来。比如输入234,以下两个号码都会显示在搜索结果中:1.1234567890002.188888823400其实最简单的解决方案是遍历所有字符串,然后用KMP算法。但是这样的问题是需要遍历10W个元素,效率比较低。我想到的是办法是使用索引。建立100个索引(00到99),比如输入234时只需要在索引23对应的区域查找即可,可以加快100倍速度。但是缺点是插入数据时,需要更新多个索引,数据量会是原来的10倍。目前还没有想到好的解决方案。有大神提醒说用字典树,有空研究一番。最后问了OC的数组中,添加nil对象会有什么问题。当时没答上来,现在想想很不应该,因为数组是以nil结尾的,如果添加了nil,后续就不能添加对象了。网易笔试:主要是计算机方面的大杂烩,涉及操作系统,网络,移动开发,算法等。难度不大,目测是为了淘汰浑水摸鱼的人,就不列出题目了,算法有三题,直接在线写(木有IDE表示很忧伤):1.很长一道题,读了很久才读懂,目测是DFS,但是最后没时间了,写了个思路。2.把“”这样的字符串改成“com/baidu/zhidao/”。——老题目了,剑指offer的,两次逆序排列即可。3.求数组中和为某个值的所有子数组,比如数组是[5,5,10,2,3]一共有四个子数组的和是15,比如[5,10],[5,10],[10,2,3],[5,5,2,3]。这个就是简单的递归了,分两种情况,当前位置的数字在子数组中,以及不在子数组中。一面:全部是iOS题,可能是觉得算法已经面过了:1.介绍block。——我提到栈上的block在ARC下会自动复制到堆上,面试官问我从iOS4还是5开始支持这一特性,表示不知道,我又不是学OC历史的,后来想想可能是公司内部老项目有这个坑。2.ARC会对代码做什么优化?——比如NSString*s2=s1;s2=nil这样的语句,可能就不会有retain和release方法了。3.介绍一下MVVM和RAC。——可能是我简历的某个角落写了用过RAC,被挖出来了,大概谈了一下,结果面试官问我数据的双向绑定怎么做,bind函数了解过么,果断说已经忘了:joy::joy::joy:4.介绍自己用过哪些开源库。——Masonry和SnapKit,AFNetWorking,MKNetworkKit,Alamofire,Mantle,SDWebImage5.如果让你写,你能实现么?——当然不能,不然还要实习?6.读过某个库的源码么?——扯了一点SDWebImage,后来被告知这个库用了runloop来保证滑动是加载数据的流畅性,自己看了源码后表示没有发现,唯一用到runloop地方是保证后台线程一直跑,也有可能是我理解错了,如果错误欢迎指正。7.SDWebImage下载了图片后为什么要解码?——当时蒙住了,面试官很nice的解释了一下,说是要把png文件建立一个什么内存映射,目前还不太懂,有空研究一下。本来以为面的这么差肯定是挂了,没想到还是过了一面。过了不到一个小时,HR电话打过来,约了两天后二面。二面:纯数学和算法:1.下面这段代码的输出结果是:cintmain(){inta[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。2.某个地方天气有如下规律:如果第一天和第二天都不下雨,则第三天下雨的概率为30%;如果第一天和第二天中有任意一天下雨,则第三天下雨的概率为60%。问如果周一周二都没下雨,那么周四下雨的概率为_。简单的概率题,答案是:30%*60%+70%*30%=39%3.某痴迷扑克的小团体喜欢用23456789TJQKA来计数,A后面是22,23,…,2A,32,…,AA,222,…依次类推。请用C/C++或Java写个程序,将用字符串表示这种计数法转换成字符串表示的10进制整数。其中,该计数法的2就对应于十进制的2,之后依次递增。C/C++函数接口:char*pokToDec(char*)我的解决思路是进制转换,类似于16进制转换10进制这种,最后再把数字转成char*类型。然后好像没结果了,可能是编程实在太渣了?其他我知道的面试题阿里一面:1.MVC具有什么样的优势,各个模块之间怎么通信,比如点击Button后怎么通知Model?2.两个无限长度链表(也就是可能有环)判断有没有交点3.UITableView的相关优化4.KVO、Notification、delegate各自的优缺点,效率还有使用场景5.如何手动通知KVO6.Objective-C中的copy方法7.runtime中,SEL和IMP的区别8.autoreleasepool的使用场景和原理9.RunLoop的实现原理和数据结构,什么时候会用到10.block为什么会有循环引用11.使用GCD如何实现这个需求:A、B、C三个任务并发,完成后执行任务D。12.NSOperation和GCD的区别13.CoreData的使用,如何处理多线程问题14.如何设计图片缓存?15.有没有自己设计过网络控件?阿里二面:1.怎么判断某个cell是否显示在屏幕上2.进程和线程的区别3.TCP与UDP区别4.TCP流量控制5.数组和链表的区别6.UIView生命周期7.如果页面A跳转到页面B,A的viewDidDisappear方法和B的viewDidAppear方法哪个先调用?8.block循环引用问题9.ARC的本质10.RunLoop的基本概念,它是怎么休眠的?11.Autoreleasepool什么时候释放,在什么场景下使用?12.如何找到字符串中第一个不重复的字符13.哈希表如何处理冲突面试收获1.算法题怎么答面试官可能会问到你闻所未闻的算法,这时候你不应该自己瞎想,而是先和面试官把问题讨论清楚。要知道,通过沟通弄明白复杂的问题也是一种能力,在和面试官交流的过程中,不仅仅可以搞清楚题目真正的意思是什么,还可以展现自己良好的交流沟通能力。所以千万不要因为紧张或者害羞而浪费这次大好的机会。有些题目似曾相识,但是暂时没有思路。这时候不妨告诉面试官,给我一些时间思考这个题。然后不要急,不要慌,就当他不存在,拿出纸和笔慢慢算(这充分说明了面试戴耳机的重要性)。你一定要坚定一个信念:“任何一道稍微有难度的算法题,除非做过,否则一定是需要时间想的”。所以,合理的安排思考时间吧。如果十几分钟都想不出来,可以直接放弃。有时候面试官会要求在线编程,相信我,他不会无聊到盯着你的代码看的,面试官一般都很忙,他也有自己的工作要完成,所以你就当是用自己的IDE就好。在线编程往往是一个中等难度的问题,所以不要自己吓唬自己。同时要注意代码格式的规范,适当的注释,提前编写好测试用例等,即使没有解决问题,也至少要把自己良好的编程习惯展示给面试官。2.遇到不会的问题怎么处理这个问题有可能是面试官故意说得含糊不清,考察你的交流能力,也有可能是无意的,或者是你的理解方式出现了偏差。不管是以上哪种问题,你都应该先和面试官交流,直到你搞懂了面试官要问你什么,而不是按照自己的理解说了一堆无用的东西。举个例子,面试官可能会问了一道算法题:“如何判断两个无限长度的链表是否有交点?”。对于“无限长度”可以有不同的理解,如果真的是有无穷多个节点,那显然这个问题是无法解决的。但如果链表仅仅是有环,那么还是可以解决的。如果面试官的本意是链表有环,但你错误的理解成了无穷多个节点,那么必然会导致无法回答这个问题。而且这并非能力不足,而是属于交流沟通方面的失误,这也正是我想分享的“技巧”。还有一些问题,虽然你没有接触过,但是由于对类似的问题或者情况有过思考,所以可以合理假设。比如面试官问“ARC会对代码做什么样的优化?”。我们知道ARC的本质就是在合适的地方插入retain和release等方法,那么就应该从这个角度出发去思考问题。显然分别执行retain和release操作是没有必要的,那么就可以构造出相应的例子:NSString*s1=@hello;NSString*s2=s1;NSString*s2=nil;由于这种问题我们没有真正实践过,所以可以委婉的告诉面试官:“根据我的推理,可能会有……”。3.遇到真的不会的问题怎么处理遇到不会的问题果断承认啊。如果是基本问题,比如问你哈希表怎么实现,你说不会,那么这次面试可能就悬了。如果是