2018 美团春招 iOS面试分享(一面)
说来惭愧,实习准备开始的太晚了。我是从3.5号开始准备的(各种原因,导师可能不放,论文第二个点没做完之类的),大致刷的是OC各种基础,牛客上面剑指offer一半的题目,常用排序和数据结构。昨晚接到的开发电话,说约个面试吧。当时心里一惊,因为没有HR通知过我呢…不过也行,检验一下自己嘛。硬着头皮就上了。
忘了说了~ 我是某985211学校滴…13年底开始接触的iOS。本来想着有人带呀…结果进了公司和学校的联合实验室(实际上也就是扔到公司里去了)后发现…等于自学啊…前前后后写了10来个中小型的App吧,虽然功能不复杂,大部分也都接触过了。好了废话不说了,开始说面试吧。
关于面试官
恩…面试官是个小哥哥(声音很好听的),很耐心,不会的时候会提示你,引导你。我是6.50坐在电脑面前等电话的,等到了7.15都没有来(第一次面试啊,心急如焚有木有)就瞄了一眼手机,正好有个电话进来又断了,响都没响的那种…赶紧回过去,果然是昨天给我打电话的开发。他说给我打了好多电话了一直打不通,哇我心里各种委屈有木有!不过在我跟对面说明了情况之后一切也就正常开始了。第一感觉,美团的面试官很nice。
面试问题(附上部分自己的答案,有错误欢迎指正)
面试问的比较广泛。之前跟内推我的同学了解过,美团一面就好像在给你开地图,探索你知识储备的边界吧。
面试总体上分为计算机网络,数据结构,OC基础和算法。有一些我记了下来的,以下详细列举。
【数】1. 数组跟链表有什么区别?
1)存储空间
数组存栈,链表放堆。
2)开辟模式
数组需要预先开辟一块空间。如果使用不满会有浪费。对动态数组而言,存放数据超出空间会另外申请开辟。
链表属于动态存储,内存不一定连续。
3)增删改查
查询而言数组更快,下标索引。增删来说链表效率高些,因为只需要操作一下指针。
【算】2. 你知道的常用排序算法里面,有哪些是比较快的?复杂度大概是多少?
最近正好有看排序,就答的快排和归并。效率都趋近于N*logN。我记得面试官补充了一下,问的是快排的最好情况和最坏情况,当时有点慌,因为没有仔细想过,模棱两可说的是最好应该会趋近于N最坏也不会差过N方。
其实对快排而言,最好的情况就是每次partition操作的元素正好插在整个子序列的中间,这样是最好的,因此最好效率是N*logN。最坏情况当然就是往两极插了,N方。
还是得多思考各种排序的复杂度情况,以及其是否稳定,为什么?这些应该都是面试官喜欢问的。
【数】3. Hash表的实现方式是怎么样的?查询和插入复杂度都是多少?附加:如果插入的时候出现冲突,解决方案?
Hash表应该也算数据结构里面一个比较基础的类型了。
大致的实现为,Hash表会根据Hash函数为每个value计算一个hash值,然后用这个hash值/表空间大小,余数就是当前对象放的位置了。这个时候问题就来了,满了咋办?位置上有别的东西了咋办呢…这就需要冲突解决方案了。一般来说有:线性探测(比如0上有元素了,我往后挪1个看看有没有,往后挪2个有没有之类的),跳跃型探测(左右闪躲啊有木有,比如+11,-11,+21,-21……),拉链法(等于变成了个二维结构)。
查询插入复杂度都是1。一步到位。
【网】4. TCP/IP 5层结构都知道吗?每一层的职能呢?
5层结构应该大家都知道。我当时很顺利就答出来了。
面试官小哥哥:给我解释下每一层都干啥。
我:……(网络还给老师了有木有)
晚上回寝室问了一下寝室里的大神,大神当场坐下不看书给我讲了半个多小时- - 记忆的技巧在于每层都只对上层负责,想想上层干嘛,下层大致也就想起来了。
1)应用层
负责应用间通讯,包含了很多协议,比如HTTP、HTTPS、SIP之类的。
2)传输层
传输层包含协议常考的有两个,TCP和UDP。为上一层提供的是端到端的数据传输(因为要端口号了哦亲)。TCP连接时的3次握手和断开时的4次挥手需要理解。UDP的话属于不太负责任的那种,不保证完整收货的。
3)网络层
这层主要就是做路由的。什么概念呢,我这个包从我这来要到哪去,怎么找路都是这层负责的。不同传输速率的路由器使用的算法不一致。这层可以理解是主机到主机之间的通信。
4)数据链路层
数据链路层主要管的是包在信道上发送时的一些问题,比如物理地址寻址、数据的成帧、流量控制、数据的检错、重发等等。
5)物理层
这层主要是做信号转换的。怎么把01字节转为电信号。算法有很多,速率不同算法也不一样。
睡了一晚上不知道理解的还对不对,欢迎指正。
【网】5. HTTP和HTTPS的基本概念?具体工作流程?如何构造安全的HTTP?(因为4.2我就没答上来,面试官小哥哥很委婉的表示,想问你这个你也不懂啊…)
这题真的是心痛…感觉面试官都不好意思嘲讽我…
根据上文所说,HTTP是工作在应用层的协议。全名超文本传输协议,通过TCP建立双端的连接,包括了客户端的请求和服务端的响应。HTTP是不安全的,它把用户请求封装成包,但是包里面的东西都是可见的(大神亲自演示抓包之后,看到了我校校园网明文传输的校园网账户登录信息…)。HTTPS多出来的那个S,多的是一个认证和加密的过程。认证,指的是“这个数据包是从正确的人手里出发的”,加密,指的是“这个数据包没有被修改过”。基于SSL进行的,现在演化到TLS啦。
【基】6. +load 跟 +initialize的区别呢?附加:+load是否需要调用super?为什么?
这个偏基础了。+load是在程序启动时加载所有类的时候执行的。 +initialize可以理解成一种懒加载,实例化某个类的时候进行。
+load不需要调用super,因为它是迭代进行的,先调用父类,再调用子类。
【基】7. category的用处?实例题:如果有个NSObject(Dog)并实现了一个run方法,直接调用[NSObject run]是否有效?为什么?如果有效的话,方法的查询/调用流程是怎么样的?
category可以修改现有类的犯法,不能添加实例变量。(protocol可以实现,但是没有使用runtime实现来的实际。)
第二个呢是有效的。从runtime的角度来说,在执行这个方法的时候,会从NSObject的分类中优先寻找名为run的方法,如果有就会执行,没有的话找本类,最后向父类进行寻找。
【基】8. mateclass…(这个就有点丢人了。因为7的缘故发散出来的题。以后细说)
这个是因为当时我回答面试官的时候只说了会先找分类(如果分类有重名方法,执行最后编译的是哪个分类的),再在本类找。因为分类中有run所以能执行(因为脑子里,NSObject上面没东西了呀,不会找父类了吧)。
面试官指正说,其实每个类都会有个metaclass,这个metaclass会指向这个类的父类。顶类的metaclass指向自己。虽然NSObject处于顶端了,但还是可以“寻找”父类的,尽管是自己。
【基】9. __block的用处?
block基础。普通变量在block里面是不能改变值的,加了__block前缀之后在block里面能进行值改变。原因是将变量从栈区转到堆区(这个我不是很确定),在__block后,变量的内存地址是有发生改变的,童鞋们可以亲测一下哦。
【基】10. 是否能给编译后的类添加属性?运行时的呢?(runtime基础知识)
这个就不细说了。runtime基本概念。
【基】11. 如果要使用runtime添加实例属性,往里传入的参数都有哪些?
这个只要思考我们@property的时候都有啥就明白了。名称,类型,参数权限(readwrite啊,nonatomic啊,strong啊之类的)和持有这个变量的类的类名。
面试官提醒:如果要更严谨一点,加个identifier。
这个可以详细看runtime的associate那块。
【基】12. runloop的基础知识。经典题目:timer准不准?mode都有几种?scrollView滑动的时候timer失效吗?怎么处理?
这个也是偏基础的。timer不是一定准的,因为受到runloop的影响。
Mode一共5种,API提供给用户的两种,DefaultMode和CommonMode。UIInitializationRunLoopMode这个mode在第一次启动后就不用了。
滑动的时候是失效的,解决方法就是讲timer加入CommonMode。
衍生:为什么加入CommonMode就能解决?说实话之前这个我没思考过,回答的是CommonMode和TrackingMode优先级一样?面试官说不对…回来查了查,CommonMode其实是一个占位Mode,把timer加入CommonMode后能同时支持DefaultMode和TrackingMode,这样就能避免scrollView对timer的影响了。
然后因为我昨天跟面试官沟通的时候问了是否需要带电脑,所以今天有手写代码的题目。
一共三道,第一道忘记了,因为面试官小哥哥说不用写了。
【基】13. 写个OC的结构体吧…(丢人丢大发了…快1年没碰OC了,之前也是CV大法的多…就写了一半…写到一半的时候,面试官小哥哥嘀咕了一句,这个题是考你的基础,我:…T . T)
这个不写了吧。其实蛮简单的,当时也大致写对了,就是类型和名称写反了。有点紧张。
【算】14. 给出两个有序数组,如何归并到一个?(这个也就是归并的主函数实现,挺简单的,不用IDE也是一下能写出来。倒是被问了如何能增强健壮性,各位可以考虑一下)
代码不上了,就是归并的排序那块。健壮性,童鞋们需要考虑的不仅仅是list1和list2是否为空(都为空,一个为空和都不为空)的情况,还需要考虑,list1和list2是否真的是有序数组?面试官小哥哥的原话是,这个是经验问题,因为你作为API的提供者,需要考虑别人会不会骗你。往往给你的都不是一个有序数组!这个时候你需要做一下排序或者返还一个异常。其实我当时想…那我还得判断有没有英文字符啥的诶…毕竟OC数组里你给我个啥我还真不知道…(面试官小哥哥会问我这个,大概是因为我简历写了我有1年多的实习经历,虽然当时公司的移动组没有,我们是第一批入驻的- - 等于自学… 其实平时开发的时候对字段的处理还是满全面的,特别是对json回来的,判空,判类型,判规范都有,自己工具类里面也有。还是因为1年多没开发了,生疏了。)
总结
其实这次的面试深度在我意料之中,偏难。确实准备的时间太短,凭着以前的记忆+临时的复习不够啊…一开始很紧张,以致于前两题都出现了更改答案的情况。这还是因为面试经验不足吧。全程中面试官会跟你不断的交流,氛围还是很轻松的。
最后面试官让问几个问题。 我问了两个。
第一个,是因为这是我人生第一面啊,就很冒昧的让面试官给个评价(知道很多面经说不让问…哎没抵抗住诱惑,毕竟人生第一面么)。S~D排序,给了个B+ -> A。(估计是挂了)
第二个,也是我最近思考的问题,移动的未来在哪。毕竟源生开发不断被H5,RN等动态化技术侵占生存空间,而且未来移动设备和PC归一化是预想之中了吧,感觉Web更有优势。面试官小哥哥的回答就先不说了。
这次面试收获其实挺大的。之前一直觉得自己想问题“足够”深,这次看来还是太浅。基础不牢靠呀…估计是挂了,也挺好,对自己有个正确的认识。好好准备准备!还有大战。
作者:就是奶牛君
链接:https://www.jianshu.com/p/301d02c7690b