北邮Google大牛本科研究生总结~

2019-04-14 18:43发布

转转:http://blog.csdn.net/vesper305/article/details/8674606 结论  在找实习找工作过程中,经历过笔试面试的洗礼,逐渐看明白了自己技术哪些方面能顶住,哪些方面是纸灯笼一捅就破,哪些方面是完全空白。 
能顶住:C++(模板、类、STL、C部分、对C++11的了解),基本数据结构与算法 
纸灯笼:操作系统、Linux、网络通信、进程线程、搜索引擎、设计模式 
空白:数据挖掘、机器学习、数据库、ACM 
这里就回忆一下我学习的过程,有些经验,更多的是教训,希望后来的人能绕过我的坑,路走得更顺些。 
  
背景 
我是北邮土著,本科是通信工程专业,研究生在模式识别实验室。 
  
大一 
下学期,《C++高级语言程序设计》,第一接触到C++。从那时候开始,我觉得C++很好玩,就认真看书,去宏福机房编书上的程序。常常是早晨7点去宏福教一楼机房上机,8点去教室上课。那时候觉得C++就是游戏,挺好玩的。 
到课程学完的时候,书上所有的例题和课后题我都编过了一遍,顺便把书上的错误给改了。直到C++上机考试的时候,我才发现,原来周围很多同学连HelloWorld都敲不熟练,我却攒了一U盘的C++例题了,C++的自信开始建立起来。 
大概也是在这时候,从我们宿舍一大牛(现在哥伦比亚大学读PhD)那里听说了STL这个东西。 
这门课结束的时候,关于C++中的C部分、类的继承多态,就有了一个比较扎实的基础。后来就是遇到问题上网查,逐渐地让自己的知识更充实。 
  
大二 
学《数据结构》,那本清华的教材我不喜欢,命名选择、命名风格、区间约定,都跟STL完全不一样,而工作了写代码肯定是遵从STL的那个约定的。 
所以,我在图书馆找了本书,《数据结构C++语言描述——应用标准模板库STL》,连续借了一个学期,上课就不搭理老师,看这本书。这是本厚砖头,但是因为是老外写的,所以词句都通俗易懂,一会儿就能看好几页,挺痛快的,不会像那本教材让人摸不着头脑。 
当然了,作业还得按教材做,我荣幸的成为班里数据结构作业仅有的几个版本之一(你懂的)。 
之后的数据结构小学期,我觉得很有意思。除了老师要求做的东西之外,自己把栈、队列、静态链表、循环队列、十字链表等等这些能实现的数据结构都实现了一遍,用模板类+异常,还是挺锻炼能力的。 
到这门课结束的时候,关于基础的数据结构(顺序表、链表、二叉树、图)和基础算法(排序、查找、堆算法)就比较扎实了。另外,从我借的那本砖头里,也学到了STL的一些容器(vector, list, queue, stack, priority_queue, set, map)的用法。 
值得一提的是,学这门课开始,我就让自己有意识地遵守STL的规范,减少不必要的麻烦。 
  
大二的时候,我还选修了一门公选课《Java语言程序设计》,计科院王晓茹老师讲的。虽然那时候课多,但是我觉得编程是件很有意思的事儿,这门课竟然不知不觉从头坚持到尾。 
王老师讲课风格比较轻松随意,对Java里面各种设计的由来也详细介绍,是相当有意思的一门课。 
就是这样,我算是对Java语言有了个入门级的认识。编写大的工程不行,但个把Java语法问题已经不在话下了。(以后的故事是,基本没有用上过,但每次用上的时候都没有掉链子,包括谷歌的面试) 
  
大二还有一门专业选修课《数据库应用技术》。这门课我学得比较水,只是对数据库知道了个大概,最后大作业也是抄的改了改。 
所以我的数据库知识,仅限于知道简单查询语句(select from where),知道一个数据表是二维的格子这些。对于高级的数据库范式什么的都不懂。 
这就构成了我的数据库水平,简历里根本没敢写,笔试面试万一遇到关于数据库的,直接缴械投降。 
  
大三 
选了门跟通信没啥关系的专业课《LINUX操作系统》,唐晓晟老师讲的,期间李亦农老师代过一次课(祝愿李老师快快恢复)。感觉两位老师讲课都很棒,自己比较水,没有全学会。但是,rm、cd这些东西还是知道了的。 
这些基本就构成了现在我的Linux水平,血淋淋的教训,凡是笔试面试遇到难的linux问题,立刻缴枪投降。 
  
保研 
因为本人脸皮巨厚,参加各种各样竞赛,锻炼了自己,认识了牛人,(意外)挣到了加分。最后以专业1/3的成绩+竞赛加分,侥幸够到校内保研名额以内,保研成功。(所以关于考研,我完全没有经验。只能说,目睹周围同学的准备过程,结论是回报等于付出。) 
  
大四 
我又选了一遍专业选修课《Java程序设计》。这次没啥可说的,就是查漏补缺,把以前忘了的Java知识补回来。 
这样有两个好处,一是这课我学过一遍,好过,容易拿高分;二是给自己增加了一个学期学Java的时间,让我在以后遇到小菜Java问题时有足够的自信。 
  
大四的时候看了本书,侯捷译的《泛型编程与STL》,感觉这本书对我学C++有里程碑的意义。 
这本书里从STL的设计哲学切入,讲述了STL为什么要那样设计,五种迭代器如何把容器与算法完美地解耦合。它详细介绍了每一个STL容器与算法,包括接口原型、参数要求、执行时间复杂度等等。 
看这本书以前,我感觉自己是在STL的树林里跑,偶尔碰到一棵树就爬上去摘点果子尝尝;看完这本书以后,感觉自己是在俯瞰这片小树林,哪儿有什么树什么果子都一目了然,想要什么都可以顺手拈来了。这感觉是真够棒的。 
以后编程的时候,总是下意识先想想STL里有没有现成的算法,如果有就直接用,简洁清晰还高效率。 
  
后来自然而然就看了《STL源码剖析》,这个是侯捷自己写的。有了前面一本书的基础,这本书里至少不会碰到不认识的接口了。这本书跟《泛型编程与STL》正好相反,从STL接口的代码实现深入进去,把STL的规格说明,庖丁解牛般地翻译成最基础的C++代码。给我印象最深的,是它里面用函数重载,把一个算法接口对好几类迭代器都特化了一遍,以一挑五,让人拍案叫绝。这本书我感觉比《泛型编程与STL》难一点,但还不至于看不懂。面试时要是有人问起STL实现细节,那这本书就可以当大招用了。
 
  
研一 
有门课有点意思,《面向对象技术与C++编程》,房鸣老师。房老师讲课不拘泥于内容,用他的思路把面向对象和C++讲活,听他的课有如醍醐灌顶,很多没想过的C++设计细节,一下子有了原因。我这门课基本是在和房老师质疑与讨论中度过的,因为房老师有时候说的东西明显和C++标准相违,我就直接站起来质疑。房老师也不生气,耐心和我讨论,要是我对了他也认。 
这门课结束后,我认为我是所有人里面从中收获最大的。这样,我对C++一些规定背后的原因有了更多的理解。可以更自信地面对C++的挑战了。 
  
研一开始跟实验室项目了,我跟的是一个校园信息挖掘的项目。我负责的任务是写个爬虫,从新浪微博爬取关于北邮的微博。就是用了新浪的开放平台,Python版,每隔一段时间爬取一下信息,去个重就完了。项目锻炼不是太大,但是还是遇到了不少七零八碎的小问题,走了不少弯路。 
  
研一第二学期,实验室组织了一个交流会,郭军老师给大家介绍一个他的研究成果,叫词激活力文本分析模型。(后来在9月份发表在了Scientific Reports上)这个文本分析模型将文本建模成为稀疏矩阵,还有一系列相关算法定义。我当时觉得这个挺好玩。 
那时候它还没有C++的实现,老师的实验数据是用Matlab跑了一天才做完的。我正好想到本科学《数据结构》时写的那个十字链表,正好可以用来实现稀疏矩阵,配上迭代器可以大大加快算法运行速度。加上其他算法也不复杂,就想动手实现一个C++的版本。另外,也正好用来当练手的项目,把什么模板、封装、容器、迭代器全都用上,玩一把。 
说干就干,记得那几天跟打了鸡血似的,除了吃饭睡觉都在实验室写这个东西,吃饭睡觉的时候脑子里也全是它。那种编代码感觉很奇妙,脑子里飞快地迭代着各种设计思路,手里一个个模板函数、类封装、迭代器呼呼地往外冒,代码像盖房子一样自己一块一块的搭建起来。这时候完全没有累的感觉,但可能是思维强度比较大,ATP消耗加快,总是感觉饿,饭量也见长。 
三天时间,第一个可运行的版本就出来了。跟郭老师要了数据,跑起来一看,他用Matlab 16小时跑完的实验,我的C++程序用39分钟就搞定了,速度提高了24倍。那叫一个欣喜若狂啊。后来不断跟同学交流,给核心程序写了一个简单的命令行参数解析,配了一些命令选项,这样比较容易使用。 
然后在一次实验室组会上,我对这个工具做了一个介绍。以后实验室用这个理论做实验的时候,基本都用我这个工具了。我呢,也得到更多的使用反馈,改正bug,增加功能,对自己也有了更多的锻炼。 
在写这个工具的过程中,我尝试了很多C++模板的使用方法,常常遇到满屏的模板编译错误,所以对模板的调试能力有不少锻炼。另外,我给把十字链表封装成一个类,还给配上了(行+列+遍历)*(常+普通)*(正向+反向)=12种迭代器,所以对指针操作、STL兼容容器实现、STL兼容迭代器实现,都有了比较高强度的锻炼。因此,我对C++有了更多的自信。
 
  
实习(找着玩) 
研一啥也不懂,看研二师兄师姐找实习,自己也跟着玩,反正也不去。投了几家忘了,最后腾讯三面通过给Offer、有道散招给了Offer,当然,都去不了。感觉有点损人品。 
笔试面试感觉还行,题目有的会有的不会,不是很过分。可能是因为没压力比较自信吧,最后结果还不错。 
  
研一暑假期间,用了大概一个礼拜,简单看完了《深度探索C++对象模型》。 
看这本书,一是因为久慕大名,有时间了想看看;二是实习面试问的C++多态底层实现,都在这本书里(也许就是出自这本书)。 
看完之后,对于C++基类派生类内存布局、虚函数表与虚函数指针、RTTI的底层实现,都有了一些认识。知道这些对编程本身没什么帮助,但是可以在脑子里闪一下代码怎么编译的,锻炼人脑编译器。 
这也就构成了我C++多态部分的知识基础,面试时的C++多态部分,全靠它了!
 
  
研二 
这个项目完成之后,又跟了第二个项目,是一个更大规模的信息挖掘项目。这个项目全是C++,代码量大,可以发挥的空间大,符合我的口味。 
但是这个过程中就发现自己有个大问题,做事情太随性,想做就做,想做哪儿就做哪儿,进度没法控制。这个问题是硬伤。后来我知道,老师差点因为这个把我开除出项目组,幸亏组里其他同学帮我才留了下来。 
这里面都是大量数据,实验室积累的高级文本算法根本上不了,太慢。所以一切回归最基本,关键词字典+字符串匹配。所以,BM算法、AC自动机,我都有幸自己实现了一下,用到项目里也真的有很大性能提高。这也是我面试说起这个项目时,最有信心的一点,只有这里面试官问不倒我。 
所以我总结,自己做的项目里,一定要有一两个能够拿得出手的地方,别人问不倒,这样才有自信在简历里写这个项目。 
  
实习 
为了准备实习笔试面试,我开始看一本书《数据结构与算法分析——C++语言描述》,并把看到的算法和数据结构都用“命名空间+模板函数+(不得已情况下)类”这套方法总结成了一个个模块,放到SVN上。这样既能锻炼编程,又能留给以后用。 
有了研一的经验,我投实习比较早,三月份就投简历。正赶上MSRA在散招实习生,就投了,竟然过了简历,竟然过了电面(是我后来的Mentor直接打电话,两次,一次咨询实习时间等硬条件,一次问简历问项目)。正式面试有两轮,一个是我Mentor,问算法;一个是IEG找的一个同事,问编程。两个我觉得表现都凑合,不好也不差,最后就过了,给我Offer了。 
再之后是暑期实习的大潮,投了几家玩,因为我觉得肯定会去MSRA。百度商务搜索部三面后Offer,腾讯三面后HR面被刷(莫非我心理有问题?),网易有道简历被鄙视,搜狗三面后Offer,微软STC三面后Offer,谷歌没找到在哪儿投简历。最后还是去了MSRA。 
在MSRA实习,才发现自己能力的不足,对面向对象设计能力为零,系统性能测试能力为零,唯一欣慰的是,和Mentor结对编程的时候,我的人脑C++编译器还算好使,能快速定位编译错误。不会就学呗,Mentor比较痛快,我干得好就表扬我,干得不好就卷我,所以还是学会了相当多的东西。最重要的,是学到了一种思维方式:彻底想明白了再做一件事,做就要做到最好。他常我说:“In Microsoft, It is your responsibility to ensure your result is right.”没有任何人帮我检查错误,我必须自己保证我给出的结果是可依赖的。 
  
求职 
先是实习生转正,三轮面试,口头Offer,正式Offer,比较顺利。但有一点很揪心,我每个节骨眼得到消息都比别人晚两天,那个难熬的劲儿,你懂的。 
之后投了几家,目标是自己感兴趣的方向,且有可能比微软给的多。阿里、搜狗、人搜,还有抱着参观食堂的目的投的谷歌。 
阿里最早面试,一面聊得很高兴,但终面面试官明显不好糊弄,一个问题把我问到死,知道彻底挂了。HR面跟终面在一起,谈人生谈理想。我心想反正也是这辈子最后一次来阿里,就侃个痛快吧。问什么答什么,跟不要钱似的。因为我要求只能在北京,所以长达俩礼拜之后,我的Offer(第n批)才到,比人家先拿的少好多。反射弧反射了十几分钟,回电话过去给它拒了。 
然后是搜狗面试,一面面试官上来就让我写期望待遇,这太意外了,我写了个不太可能的数。面试还算顺利,面试官很nice。二面的时候主要是聊天,关于技术的项目的,说了不少,但暴露出我自己比较水。至今备胎中。 
人搜通知面试比较晚,一面问算法题,二面过简历,比较常规。估计简历吹得有点大,被问出水来了,所以至今没有三面,备胎中。 
去谷歌面试,完全是想参观食堂,结果保安一直看着我,加上都是下午面试,没机会进。一二面在一起,都是算法题。吃晚饭时,接到电话第二天三四面。第二天三四面在一起,算是编程题和设计题吧。这和我印象中谷歌的面试题完全不一样,印象中只有ACM大牛才能做出来的那些难题,我都没有遇到。后来就是继续等电话,HR通知发成绩单,等结果,Offer。 
其他不打算再找了,因为想留在互联网,手里的Offer都大大超出自己的设想,有点懵。我对自己能力的评价是,踮着脚能够到微软的Offer,但Google、Facebook、Hulu这类只是想想而已(对这几家公司情况也了解太少)。 
  
总结 
我实验室一师兄总结我:没有刻意去追求什么,每一个阶段都是做自己想做的事,这样挺好。 
当然了,要是自己就想天天睡觉,那也别指着天上掉Offer(仅对我等屌丝成立),该付出的总要付出。