关于一场奇葩的微软面试

年底这几个月没啥业务,我在苏州已经待了快两年了也没有认识一些苏州的IT人士,于是想趁这个阶段去熟悉&了解一下苏州的IT环境。我想到的办法就是投简历,那么苏州的地头蛇就是微软,所以马上在知乎上搜索到微软的同学求了一个面试的机会。

面试总共分3个阶段,第一个阶段是电面(Skype),第二个阶段是做一个线下的工程,第三个阶段是最后一次现场面试,总共耗时还挺长的大约前后一个月。

微软和Google一样也是算法和经验都要面的,所以在我计划面试前先复习了一周,前3~4天复习算法(以前刷过LeetCode)把一些基本的思想,递归/分治/动规都又看了下并做了些练习,后几天把Android/Go/游戏相关的东西都看了一遍。此处不得不说作为大龄程序员的苦恼,掌握的技能太多,不把所有技能写出来,感觉对方会觉得你干了这么多年还这么点经验,写吧又给自己增加负担,万一面试官也懂这一块正好问下去怎么办?所以虽然我投的是Android,但是我把游戏开发/图形/后端/Go相关的东西也准备了一遍,比如你问我Go的内存回收算法,我张口就可说出来...

第一阶段

第一面本来应该是Skype的,不过我想去认人交流的,所以我直接去了那边,面我是一个微软的Android工程师(隐私,大名就不提了)。先聊了聊我以前的工作和我之前搞的一个架构,然后是MVC/MVP/MVVM这些架构,过程还是蛮开心的,我也好久没跟人切磋过这些东西了,最后是一个算法比较简单(白板书写):

有一个字符串由0-9之间的数字组成,判断这个字符串是不是可以分割成一个合法的ip地址?

我用的是递归的思路,每次处理一个子串搞定。只是过程我做了很多修修补补,这个两方面的原因:

  1. 我现在用的主力语言是Go,但是面试的时候用的是Java,所以声明变量的时候我总会写反了,比如应该是 int a ,我总是不自觉的写成 a int,所以经常擦
  2. 第二是我复习的时候用电脑写的,可以随便插入代码。但是白板写的时候不能插的,需要提前构思好再写(还需要预判多少行,不然白板不够写的)

(以上也算是白板面的一些经验,感兴趣的同学面试的时候也准备一下)

跟面试官聊的比较开心,我也毫无保留的把多年的想法和经验跟面试官交流了下,这一面算是过了。

第二阶段

做一个线下工程,说句心里话,如果我早知道还要做线下工程的话就不投微软了,我本来的目的也不是取这个饭碗而是结交和认识苏州的IT人士,现在还要做工程投入超出了我的预算。这个项目的地址在 outlook/jobs 做一个类似的效果出来(一周的时间),前两天正好有个项目我就没看,打算周末看看,结果发现竟然还“挺难的”,这个效果我分析了一下。基本锁定了方向 - ListView/Gallery/ViewPager/RecyclerView,用这些东西一定可以做出来的,但是Gallery已经被废弃肯定不能用,我先用ViewPager实现了下面的效果(让ViewPager竖着滑动效果),然后计划用 ListView 实现 Gallery,但是这个过程比较麻烦, ListView是一个比较封闭的对象自定义的时候坑是很多的,我写了一天就放弃了。其实我知道 RecyclerView 可以更容易实现这个效果的,但是这两年我已偏离Android航道很久没有实际的自定义经验,如果从头学的话不知道要多久(这也是我说难的原因)。但是我还是决定啃下这个骨头,先从 Google 的 Sample 里面找到了一个自定义的Demo,大概熟悉了一下(做的过程中我又发现了SnapHelper)结果很愉快的就是实现了。然后又花一天写了两个View 联动的效果,测试几个方案,最后找到了一个不错的方案,代码在 ntop001/ms-contacts 有兴趣的同学可以看看。最后一天我复查了一下代码加上注释就提交了,总共耗时4天(我宝贵的时间呀!)

第三个阶段

这个阶段就是最后的现场面试,第一面依然是一个Android研发的小哥,不过这个小哥有点不爱说话吧,我一直觉得有点压抑。先问了架构的东西(其实早前已经说过一次了),这次就按部就班的又复述了一遍,然后是算法,这个算法是:

实现 SparseArray 里面的put算法?

这个算法也不难,我分析了一下这里的核心算法抽象为:如何在一个有序数组中找到一个合适的插入位置,使这个数组依然有序,作为已经做过复习的人来说 so easy!并且吸取了第一阶段的经验,(来之前)我还专门在小本本上用笔用Java语言写了好多遍,现在手感也有了。所以一次成型,大概就是这样:搜索插入位置 我做了些修改但是主体没变,这个写法是二分法中最保险的写法,因为我在做游戏引擎的过程中经常用到所以也沿用了这个写法,小哥哥初看我这个写法的时候还有点惊诧,说 left+1 < right 这种写法不常见有点小毛病。其实没有小毛病的,他可能是估计我会用left <= right 或者 left < right 的写法然后看我如何处理这里的边界条件吧. 然后我解释了这个算法巧妙之处,他说可能 make sense, 这样这一面就算过了(还有个关于DELETED对象的问题,我写的中途竟然忘记了小哥哥提示下基本解决问题)。

接下来是 “老大” 面了。

奇葩的第三面

这一面真的很奇葩,我至今为止都没有搞清楚那位老大要问我的是什么问题,或者说痛点是什么?“老大”(可能也不是大老大.. 邮件中也没说)进来后第一个问题:

你能给微软带来什么价值?

这是一个老生常谈的话题,最近几年也不怎问了不知道竟然有这一问。我说这取决于我在微软做什么,如果是研发的话,我能写出可靠的代码,如果是做管理的话(有点管理经验)我会协调好项目的进度和管理好员工的预期。然后老大就说你是研发,于是我就从过去的研发经验开始讲了,我心中的主题是围绕可靠的代码,于是我讲了TDD和CI这些东西. 接下来老大出了一个题目,问我怎么解决(抱歉的是我无法把这个题目描述出来,因为我不知道他在说什么)大概上下文是:

你用过 Outlook 客户端吗?我说没用过,我一般都用网页版的客户端。他接着说如果你用 Outlook 那么它可以接入不同的邮件系统,比如Hotmail、Gmail,每种邮件都有日历,日历上的事件会有冲突,Hotmail和Gmail的日历也会冲突...

这大概就是上下文了,注意我没写问题在哪儿。然后要我解决这个 “问题”,说实话我都不知道他说的问题在哪儿,怎么解决问题呀?(其实从领域驱动设计的角度我立刻提取了几个关键词 -- 邮箱、日历、事件、冲突)我想了一下提到了事件“冲突”难道是解决这个问题,于是我总结复述并确认,得到的答案是:否!于是接下来进入死循环了,我不断的捕获他的意图,并向他确认但是总是“否”... 于是我甩出了第一句让他很不愉快的话,我说,无论是什么样的系统或者是什么样的难题,对于用户来说都会有一个预期比如我做引擎的时候有一个简单的预期是 “在屏幕上画点什么” 于是我会从这个预期出发不断的分解问题并解决问题(其实我心里还在想,我给客户做东西的时候客户只有一个模糊的观念我都可以通过不断的问与答得到最终用户要的东西但是你一直在否认,自己又不说我怎么给你解决呀😂😂)。我说了这点之后,它说那就按你自己的预期来吧,于是我按照自己的预期:用户需要有一个中心化的地方来查看这些事件知道自己的日程安排是否有冲突了。他说可以,于是我说设计一个底层业务系统把所有的事件统一起来,计算出一个列表扔个前端做渲染就可以了。然后他说前端怎么渲染我说前端可以按照Gmail那种通过不同的颜色来区分,如果是没有冲突的事件画绿色,有冲突的事件用半透明的红色,这样多事件冲突的时候颜色加深可以给用户一个很直观的提示。我以为问题就这样愉快的解决了,然后他说我没有解决问题.... 擦,我都不知道你啥问题,于是又死循环了一段时间。

接下来他说你等下我们商量一下给你结果。我觉得有点不忿,说了第二句让他直接送我走人的话,我说:这其实是一个很简单的“问题”,但是你一直不把问题描述清楚(包括我的提问也直接没有理由的否定掉)这样是我无法解决这个“问题”的。然后他说(语气有明显变化,估计生气了),我现在就可以送你走了... blabla...

于是我就乖乖的走了,结束了今天最奇葩的一次面试。回来的路上我还在想他的点究竟是什么... 直到我把这篇文章写完,也还不知道... 感人😂😂😂

总结

总的来说,微软的研发还是挺厉害的(年龄也偏大),算法和工程也不错比较符合我的预期。但是对于微软的面试并不看好,流程太长了耽误时间(尤其是工程部分,这种方式额外的要求面试者付出更多的劳动来弥补面试官自身考察能力的不足)。说实话接下来的面试,对方压根就没有问我任何关于之前做的那个工程的问题,算法部分比较简单也不需要准备太多(可怜我还重点练了分治/动规,结果人家只问了easy+的问题),面前在小本本上演练下白板一次成形很重要,一面的小哥专门叮嘱过我。另外就是,我也聊过投资人、各路CEO,但是没见过这样的“老大”,面试是一场交流互相探底的过程,而不是纯粹的否定,被送走的时候我突发奇想问了他的年龄,40多的人了...

关于收获,微软的研发还是厉害的,但是比较封闭人也比较傲娇不爱跟其它公司交流。薪水其实并不高,HR跟我说如果我面进入了薪水比我两年前在上海的薪水(我两年前和四年前的薪水是一样的跳了一家公司并没有涨薪)还低并不是知乎上说的比北上略低。另外告诉大家一个关于大公司“永远在招人”的小秘密,很多大公司都说自己严重缺人其实都是套路只是年度的HC在那里放着,用来在市面上以高性价比捡漏子而已,项目组本身不都是必须的,所以无论什么年头分明已经开始裁人了但是依然会看到有项目组说缺人的情况,听听就好我们曾经三个月招一个人就是因为任性。

编辑于 2019-01-23