目录
什么是Project Intern?
Project Intern希望能让更多SoC的学生获得科技公司的暑期实习机会。这个网页也是项目的一部分。我们希望可以收集到所有有关暑期海外实习的信息,其中侧重于:
- NUS SoC 的学生
- 美国科技公司的暑期实习机会 [1]
[1] 并不是说在美国之外就没有有趣的实习机会。过去SoC的学生在瑞典、加拿大、日本和英国的公司曾获得过各种实习机会。但说实话,那些规模最大、最令人感兴趣的科技公司都位于美国。每个夏天,世界各地的人才涌入硅谷,挤满了公寓、旅馆、车站;hackathon、草坪与各种活动上满是他们的面孔。(这样的场景在别的地方自然也不少见,但硅谷绝对是最典型的)
这意味着,你将会遇见许多才华横溢的人,也会从中收获很多的欢乐。当然,既然你将会在这样的环境中度过3个月,你一定也会学到很多。
Project Intern关注两个方向:
- 提高学生对海外实习的关注度
- 帮助学生争取到海外实习的机会
本页也将会探讨以上这两个方面。
为什么要参与暑期实习?
你是一名大学生,刚刚熬过你在NUS的又一个学期。这时候你估计正在等待考试成绩,担心自己的CAP,准备着与朋友的旅行计划(泰国、越南、巴厘岛,想去哪个?)。干嘛要去实习呢?
选择实习有这么几个原因。
在暑期实习的这段时间里,你将会在一个公司工作三个月。这三个月中你将会像一名正式员工一样工作。在硅谷,规模比较大的公司(如Google、Facebook、微软、Palantir)会支付7000到8000美元的薪酬,另加免费的住宿、伙食、自行车、笔记本电脑等等。具体的待遇取决于公司有多大,人事部有多疯狂。而硅谷的创业型公司会支付3000到8000美元的薪酬。具体水平取决于公司的规模以及你在实习期间所扮演的角色。当然,只有规模类似于Quora这样的创业公司才会有接近其他大公司的待遇。
那么,理由之一:你会挣到很多的钱。远远超过你用父母的钱去巴厘岛玩一趟的开支。(这个,当然你同时也会花钱嘛,Amazon Prime什么的……咳咳……)
当然,仅靠工资作为理由还不够。下面有一些比较明显的理由:
理由之二:你会学到很多。如果你希望将自己的专业变成自己的专长,那你应该聪明地学习。拿到一个实习的机会能强迫你强化计算机科学的基础。在硅谷实习期间你将会遇到这个领域中最优秀的一些人。这段经历所教给你的那些关于计算机科学以及这个行业本身的知识,是你独自在书本中永远都学不到的。
当你有了这样的经历之后,再次回到课堂时你将会对教授所讲授的内容有新的认识与理解。你将会发现更多有趣或有用的事物。讲义上机器学习的公式可能还是和以前一样无聊,但你将会明白为什么它能够如此地热门。你甚至会开始读论文,为未来的技术性项目寻找点子。
理由之三:你可以体验毕业后工作的感觉。科技公司的实习机会是一次全职工作的体验。你有三个月的时间探索这样的工作是否适合你。如果你喜欢这份工作,你实际上已经一只脚跨入这家公司的门了。哪怕你未来不在这个公司求职,你也仍然会从这次实习中受益——想想看简历上有在Google、微软、Facebook或其他公司实习的经历能为你带来多大的优势。
理由之四:你会过得很快乐。美国可以去的地方太多,可以做得事情太多。去Gilroy购物,去Napa品酒、去Portola Vally采水果,参观现代艺术博物馆,跳伞,参与当周的hackathon(每周都会有hackathon,真的),或者去约塞米蒂国家公园远足……你面前的选择太多太多。海外实习生就像是海外交换生一样,但你不仅不用上课,还有人付钱给你!
谁在招聘?
以下公司都曾在NUS招收过实习生[1]。
- Microsoft
- Palantir
- Quora
[1] 对公司来说,招聘国际实习生会带来更大的负担,因为他们需要处理签证手续,还要花更多的钱在机票和住宿上。
别把目光局限在这里的几家公司上。同时向多家公司提交申请会大大增加你获得offer的机会(科技公司忽视优秀的应聘者的概率实在太高,简直是臭名远扬了)。
应聘过程
不同公司的招聘过程各不相同,但往往有类似之处。以下是一个典型的应聘过程。
典型应聘过程的概述
1. 提交简历(发起联络)
这是你需要迈出的第一步。你可以寄出简历,找一位推荐人或联络一名招聘官。很多人连这一点都做不到。他们认为自己毫无机会,所以连试一试的念头都没有。
如果你不主动发起联络,没有人会雇用你。
2. 招聘官选中你的简历并与你联络
在上一步与这一步之间,往往是痛苦漫长的等待。很多人根本不会得到招聘方的回复——想想看招聘方要收到多少简历,而又能一对一联络几个人。如果没有得到对方的回复,不要灰心丧气。改进你的简历,再试一次。
3. 电话筛选
你可以将电话筛选过程视为是简化的技术面试。这个过程要求不高,通常技术性也不强。这一关的目的是筛选掉那些纸上看起来不错,但实际上没什么本事的人。
4. 技术面试
通常这里有两场面试,每场大约一个小时。面试的形式可能会通过Skype或是电话进行,并附有在线协作文档供你写代码。
大部分人由于准备不足而在这一关落马。
(后文有关于技术面试的更多细节)
5. 现场面试(各有不同)
有些公司会有这一项,而有些公司只对全职工作的应聘者有这一要求。有些公司这是让他们的工程师飞到应聘者的所在地对他们进行面试,而不是要求应聘者飞到公司来。每个地方的方法都不一样。
6. Offer
恭喜你,你成功了。现在是决定是否要接受这份工作的时候了。在你签下自己的大名之前,尤其是你面前有不止一份offer的时候,你可能应该先考虑以下几点因素。
- 产品 - 你会参与什么产品的工作?你是否为此感到兴奋?
- 待遇 - 除了薪水之外不要忘记考虑进去税款、食宿、生活开支。这些数字加在一起不是个小数目。
- 位置 - 这个因素纯碎是个人喜好。假设你是要去美国实习,你可以考虑去一个以前没去过的城市工作。
何时开始申请
尽早申请。
如你所估计的一样,暑期实习的竞争非常激烈。你将会和世界各地的学生争夺实习的机会。申请最早在秋天(暑期一结束)就开始了,随着时间的推移,名额越来越少。最晚的窗口大概是暑期前一个月,但机会不大。申请得越晚,公司和团队内的位置就越少。显然,越有吸引力的公司和团队,都是最先被抢光的。[*]
[*]比如Google X或微软研究院
简历
这是学生面临的最大障碍之一。作为学生我们真的没有多少可以博得应聘者眼球的经历可以写到简历上。不过好消息是大部分人,至少还没有过实习经历的应聘者,他们的情况都与你差不多。最重要的一点是技术性简历与普通的简历不一样。
以下这些优秀的资源展示了如何正确地准备简历:
- http://www.careercup.com/resume
- https://www.quora.com/Job-Search/What-are-common-mistakes-that-applicants-make-when-writing-their-resumes-for-tech-companies/answer/Gayle-Laakmann-McDowell
- http://www.youtube.com/watch?v=rEJzOhC5ZtQ - Gayle Laakman McDowell,曾在微软、Apple与Google担任软件工程师,并曾经是Google的招聘委员会成员。很不错的观点。
技术面试
作为应聘者,你应该具有以下知识(但不仅限于此):
- 基础编程技术(会写代码)
- 理解相关的语义——基本表达式、组合、抽象 (primitives, combination, abstractions),即使不能明确地表达
- 算法与数据结构——你应当完成了算法与数据结构的课程并获得较好的成绩,或者已掌握相关的知识
- 对系统设计与数据库设计的敏感性——理解所涉及到的取舍与利弊
- 至少熟识一种编程语言,面对新语言可以快速上手
- 逻辑、形式系统与证明系统的基本知识
- 解决问题的能力
面试形式
各个公司的技术面试形式各不相同。通常说来,大公司(Google、微软、Amazon)的面试通常有成熟的系统,往往更容易预测,比较一致。而小公司(如创业公司,甚至Facebook)的面试则往往取决于你所遇到的面试官。但总的说来,技术面试中有一些常见的模式。
面试可以采取面对面的形式开展,也可能通过Skype或是电话会议,配合在线文档合作编辑工具,如Google Docs或Stypi进行。根据面试形式的不同,你可能会在一场面试中面对多个面试官,或是进行多轮面试,每次面对一名面试官。绝大部分的面试不会超过一个小时。
面试官会问的问题通常可以分为如下四类:
- 设计 - 面试官会问你如何设计某个特定的功能(包括后端、数据库等)。比如,问题可能会是如何设计一个简化版的Facebook新鲜事功能。
- 编程问题 - 面试官会给你一个问题,并要求你实现解决方法。最常见的问题是算法问题,但也可能面试官会即兴提问。有时候面试官会想考察你的编程基础能力,或针对某种你自称熟悉的语言进行具体的考察(如针对C/C++中指针的问题)。
- 测试问题 - 面试官将问你如何测试某个特定的功能或代码。
- 逻辑谜题 - 脑筋急转弯之类的问题越来越少见了,但仍然可能会出现。
你应当注意以下几个要点。
通常都需要权衡利弊
面试官的目的是在有限的时间内对你作为工程师的能力进行检测。作为一名工程师,你应当具备的能力之一是能够理解并权衡作出决定时所涉及到的利弊得失。比如,你可能会被要求设计一种用于存储数据的抽象数据结构(例如模仿数组的结构)。你可以简单地从一个数组起步,但当你的静态数组达到容量上限时你会遇到问题。这时你可以换用链表,但你会遇到内存碎片的问题。在这里,你需要权衡利弊。面试官可能会引导协助你,但你应该尽量从开始时便注意这一点。
提出假设
注意你使用的假设。这一点对所有类型的问题(设计、编程……)都适用。例如,当面试官要求你实现一个过程时,一般人都会假设传入的参数是有效的。虽说这是一个比较合理的假设,但你不妨先和面试官确认这一点,并在实现解法时采取防御性的设计。
面试的走向
再强调一次,面试注重的是你是否能胜任工程师的角色。因此,面试很可能根据你给出的答案甚至你提出的问题而改变。比如,面试官可能会要求你写一端检查括号匹配的代码(如()()((()))
是合法的,而())
则是无效的)。可能你会回答使用正则表达式来处理,那么即使面试官的初衷不是考察正则表达式的能力,他可能仍然会顺着你的回答,要求你实现这一解法。不过仍然不要忘记权衡利弊(速度、内存、代码的简洁与可测试性)。
不可以说自己“擅长”哪一方面
首先,这是谦逊与否的问题。展现你的激情,而不是你的傲慢。搞清楚自己的位置。其次,想想看如果你说自己擅长C++,却败在一道基础的C++编程问题上会有多么尴尬。
简单的问题
不要低估那些看起来简单的问题。永远要保持“这是一位经验丰富的面试官,他问这个问题一定有特殊的目的”的假设。这样的问题可能有一些你一不小心就会忽视的特例,或是有一些你没有想到的高效解法。面试官也可能想看看你写的代码是否优雅。比如前文中括号匹配的问题是一个简单的编程问题,但能力不足的程序员往往会写出冗长而杂乱的代码。毕竟,工程师的工作就是通过不复杂的代码实现各种过程与模块,并尽力做到优雅、简洁、可维护。
不过也不要在简单的问题上思考太多。这可能只是一个热身问题,或是其他问题的前提铺垫。
说出你的思维过程,与你的面试官对话
不要直接就开始说问题的解法。仔细想一遍问题,并做出规划。让面试官听到你的思维过程是一个有益的解题方式。你应当把整个面试过程视为是你与面试官之间的一次对话,目的是让他更好地了解你。当你在一个问题上卡壳时,大胆求助(当然,先尽量自己思考)。
通常(在面对面的面试中),现场会有一块白板。把那块白板当做草稿纸,供你思考,并说出你的思维过程。利用白板帮助你与面试官讨论这个问题为何要用这种解法来解决。
如何为实习做好准备
这可能会是一个令人怯步的过程。对一些人来说,你可能刚刚开始接触计算机或编程。你可能在考虑如何才能赶上别人。好消息是你有足够的时间。现在开始并不晚,你绝对可以达到一个实习生应当具有的水平。
作为第一步,请先去读一读这份文档: Notes to Computer Science Freshmen, From The Future.
欢迎回来。如果你直接跳过了上面的链接,你应该回过头去先读一读。那里面有很多与你一样的学生写下的道理,那些他们希望自己可以早一点明白的道理。
这份文档为这一章提供了一个良好的基础。它包含了如何在SoC或是计算机科学这个领域站稳脚跟的建议。绝大部分对于赢得一份科技公司的实习机会大有帮助。毕竟如果你的学业优秀,那你获得你所梦寐以求的那份实习工作的机会能大大提高。
针对NUS SoC的建议
需要用心去学的必修课
以下是所有学生都要学习的必修课。但学生很容易忽视他们,或是未能给予足够的关注。比如很多学生认为离散数学纯粹是在浪费时间,所以没有用心去学。
CS1231 - Discrete Structures
所有新生都需要学这门课。它超级重要。不要忽视这门课,也不要在感觉课程太难时轻易放弃。
CS2103 - Software Engineering
对大部分人来收,这将会是他们的首个软件项目。这会是一次体验应用设计,处理较大的数据库,并提升自己编程能力的机会。
应当考虑的选修课
CS1101S - Programming Methodology
在你的第一个学期,你要从CS1010和CS1101S中作出一个选择。请选后者。真的。虽然CS1101S在时间和精力上显然有更高的要求,但这门课的压力对你会大有帮助。
此外,CS1101S与CS1010相比绝对更接近顶尖学府的编程入门课程。面对实习的竞争,为什么要选择较难的课程,理由想必很明显。
大部分新生都错误地认为,自己刚接触计算机科学,所以应该选择较为简单的课程,循序渐进地学。很多选了CS1101S的学长都完全没有编程基础,但他们学得都不差。当然,这也有例外。如果你认为你没有应付较高强度的课时压力,你应该向你的学长,或者是教授咨询。
有一些人冲着CS1010是一个免费的A而去学这门课。说真的,没有东西是免费的。想想看你为这个所谓“免费”的A付出了什么。
CS2020 - Data Structures and Algorithms Accelerated
在你的第二个学期,你要从两个数据结构与算法的课程中选择一个。第一个是“加速”课程,包含一个6学分的课程。另一个是包含两个4学分的课程,在两个学期内完成。
如果你有能力(你需要在CS1010或等价课程中获得至少为A-的成绩),你应该选CS2020。数据结构与算法对于实习机会有多重要已经强调过很多遍了(参见技术面试一节)。更早地学习这些知识意味着你有更多的时间思考他们并应用到实际中。
CS2020同样也更接近顶尖学府中的同等课程。
CS3230 - Algorithms
认真地对待这门课。出于学生人数的限制,往年这门课都无法在最理想的状态下开展。但绝不要轻视算法、证明与基础复杂论的正统知识的重要性。
其他该做的事情
教课——尽量成为一名助教
如果你有机会,去当一名助教。在教授别人知识时,你自己也在学习。很多人因为教课会花费太多的时间而放弃。这是事实,所以请规划好你的时间。
公司看中简历中的什么内容?
成绩。GPA究竟有多重要?
这很难说。大部分的招聘方对美国满分为4分的GPA系统比较熟悉,但NUS的CAP是五分制的。无论如何,成绩应该不是最重要的因素。
你的成绩不能太差。毕竟对大部分应聘者来说这是你“虽然不完美,但学会了应该知道的东西”的信号。但尽管如此CAP的绝对分值对公司来说,没有这里说到的其他几个因素重要。
个人项目
个人项目的重要性实在是太重要了。除非你有别的方法能证明你会编程(比如在信息学奥赛上获奖),不然这是你证明自己能力的最佳途径。
作为在校学生,你的简历上应该基本都是一些不相关的经历,比如兵役,某个学生组织的领袖,社区服务等等。不是说这些因素不重要(你的确应该把这些内容放进简历里,展示你其他方面的优点),但公司绝不会单单因为这些因素而雇你去作软件工程师的。
他们所想看到的是这些:
- 你能写代码
- 你对你做的事情充满热情
- 你能够自学知识
个人的项目是实现以上三点的最佳方式。此外他们还为你带来了宝贵的学习经验。做一些你想做的东西。更好的方法是学习Git,把你的代码分享在GitHub上。nusmods.com是一个个人项目的绝佳例子。你很快就会用上它,或者早已用过了。
为技术面试做准备
这个标题其实很有误导性。它似乎在说,你可以在短时间内为面试做好准备。实际上除非你的知识掌握得非常好,并有优秀的能力,否则你需要更多的时间。
等你知道你有一场技术面试时才开始准备,那时已经太晚了。
数据结构与算法的知识,解决问题的能力与写代码的能力都需要时间来积累。要想有明显的进步,你至少需要几个月的时间。所以尽早开始,持之以恒地练习。这些技能为你带来的好处绝对超越技术面试本身。
这里有一些针对各个方面如何进步的建议:
数据结构与算法
有一本算法书对你的帮助一定会很大。对本科学生来说,公认的教科书是《CLRS》。虽然网上有很多盗版的版本,我们强烈建议你不要这么做。首先这是违法的。更重要的是,你在这本实体书(或是Kindle电子版)上的收益会远远超过你的投入。想想你的大学学费。买一本优秀的教科书的成本远远低于学费,但对你的帮助可能比你选的一些课程更大。任何想要好好学的CS学生都应该至少有一本优秀的数据结构与算法的书。
花大量的时间仔细地阅读。理解其中的证明。
编程能力
广泛地编程。你在编程上花费的时间越多,你的能力就越高。并不是说你一定要去实现复杂的算法或机器学习系统。简单的网页应用配合一些逻辑代码就会很有帮助。你在练习上花费的时间会帮助你训练并提高用优雅简洁的方式实现某种逻辑的能力。这对你大有帮助。
除此之外,要敢于尝试。如果你在写代码时一直感觉都很好,这不是一件好事。当你学到一个新的算法或数据结构后,去用你喜欢的语言来实现它。多玩一玩,去优化它,理解它,消化它。
多读代码。网上有很多开源项目,其中有大量的优秀代码供你学习。很多程序员都在他们的网站或博客上分享针对某一个数据结构或算法的代码。试着去实现一些,然后看看其他(更聪明、更有经验的)人是如何实现的。你能从这之中学到很多。你会了解到你之前从未见过的编程语言结构和语法糖,或是一些非常基础,但能够让代码变得更优秀的模式与风格。
解决问题的能力
// TODO 这里强烈推荐一本书(不过有些老了)
How to Solve It by George Polya.
技术性问题
拥有编程竞赛的经验会很有帮助。这能增进你对数据结构与算法的知识、提高编程流畅度等。你可以考虑买一本NUS的讲师写的关于竞赛性编程的课本。网上有一个免费的工具http://uhunt.felix-halim.net/,将大量的UVa习题分类。如果你希望系统地提高自己的核心算法知识,可以考虑用它。
一个坚实的数学基础非常重要。不论课程看起来有多陌生或困难,都不要忽视你的数学课(特别是CS1231和CS1101R)。
面试技巧
// TODO
Whiteboarding and the meta-game
// TODO: better classification with the above section (interview skils)
记住,面试(尤其是面对面的面试)是面试官考察你是否适合公司的时机。这不是自动化测试(你不会因为打错问题而落选)。如前文所说,好好利用现场的白板。
用计算性的思维考虑问题。以下两个谜题来自两个大公司的两个不同面试官:
你有一种特殊的鸡蛋。当它从某一个固定高度 H 米坠落时,则会摔碎,其中H < 20。你有四个这样的鸡蛋,在最坏的情况下你至少需要几次试验方可得知H的数值?
现在是深夜,前面有一座只能容两人通过的桥。四个人在桥的一侧想要过桥,但只有一个手电筒。他们过桥的时间各不相同(分别为1秒、2秒、5秒和10秒)。在过桥时他们需要手电筒照明(所以两个人过桥时,他们会以较慢的那个人的速度前进)。四个人最少要多久方可全部过桥?
当然你应该按原样解答这些问题。随着你对问题理解的深入,发展出一个概念并(通过白板和说出你的思维过程)展示给面试官,让他知道你在系统地解决问题。他们会欣赏这样的思路。但你需要注意的是,虽然这两个问题都有特定的数值,但他们都可以被抽象成一个更一般化的问题。一般化的问题可能可以通过运算而找到答案。即使这不是面试官的初衷,你也可以指出这一点,并于面试官讨论。例如第一个问题实际上是一个经典的动态规划问题。
大部分情况下,如果面试官给出一些谜题,它们通常会与计算机科学中的一些概念相关(熵与数据压缩、掩码表达、可满足性建模、约束问题、有限状态机等等)。大部分关联通常不明显(有时候甚至连面试官也没有想到!),但如果你能发现个中关联,则会大有帮助。
在解决谜题的时候,不要满足于找到问题的答案。这是很多试图轻松快速地掌握面试技巧的人常犯的一个错误。他们收集阅读大量的面试问题,了解解法,然后开始学习下一个问题。有时候这样的办法也许会成功,但总有一天你会碰到一名优秀的面试官,他能够看穿那些试图游戏规则的学生[1]。如果你想到了(或读到过)问题的解法,你应该进一步分析这个问题。试图严谨正式地证明你的解。考虑哪些假设或问题中的前提使得这个解成立。与朋友讨论这些问题。这些对你解题能力都有帮助。
[1] 大公司的面试官通常都经过严格的训练(如工作坊、旁听面试等)后方可开始进行面试。
非技术性的问题
诚实地面对自己。向朋友和导师收集反馈,自我反思。这能让你变得更真诚,并真的会在面试中体现出来。
在电话面试和技术面试中,你可能会被问到如下这些常见的传统问题。
“你认为你最大的弱点是什么?”
在面试快结束时,面试官会问你有什么问题。一定要提前想好这些问题。它们也许不如技术性问题重要,但人们往往忽略它们。记住,面试你的人同时也在将你作为一个个人来评价你,考虑是否愿意与你一起工作。这是不涉及技术,但同样重要的。
你的简历在帮助你通过最初的筛选并获得面试机会外,还有其他的作用。大部分的面试官在面试时都会有一份你的简历。这是一份对你个人的陈述,所以你应该仔细地准备它。考虑好你想通过简历来告诉面试官什么——这是面试中的一个重要工具。把你希望谈论的话题放入你的简历。面试官会从你的简历中看到这些信息并向你提问。
资源
- http://alexeymk.com/a-brief-guide-to-tech-internships/ - 关于为什么应该去实习、如何获得实习机会的建议的一片好文章。
- http://www.amazon.com/books/dp/098478280X - Cracking the Coding Interview,其中讨论到招聘流程,技术面试的技巧和一些问题供你练习
- http://internproject.io/finding-an-internship/coding-resumes-differ/ - Cracking the Coding Interview的作者所写,教你如何让你的简历符合你要申请的公司
- http://steve-yegge.blogspot.com/2008/03/get-that-job-at-google.html
- www.quora.com/Algorithms/What-are-the-ways-to-utilize-6-months-to-build-skill-set-to-get-into-Facebook-or-Google
- https://www.quora.com/Engineering-Recruiting/What-should-I-do-in-the-next-6-months-to-get-into-a-company-like-Amazon-Google
- https://www.quora.com/Algorithms/What-are-the-ways-to-utilize-6-months-to-build-skill-set-to-get-into-Facebook-or-Google/answer/Nandish-Punter