在黑板上或纸上写代码的算法部分是工作面试中最重要的阶段之一,对于开发人员来说,要在Yandex中找到一份工作。 我们决定更详细地讨论这些部分的组织方式,以帮助将来的候选人进行准备。 另外,我希望许多不敢去Yandex进行采访的人,害怕审判太困难,在经历了这个故事后,会明白实际上一切并没有那么可怕!
因此,我们为您准备了以下材料:
- 一项特殊竞赛,包含与我们为面试提供的任务相似的任务。
- 这个帖子 。 它说明了您为什么需要进行此类部分以及了解比赛的所有任务。
- 整理了比赛中任务的两个视频:第一个 -任务比较简单, 第二个 -困难两个。 从这些视频中,您将了解通过算法部分以及编写生产代码时常见的错误。

我们如何采访开发人员
对任何开发人员的采访都包括以下几个阶段:
- 招募人员的预科;
- Skype技术面试;
- 几个全职部分;
- 对招聘经理的最后面试。
在预备课上,招聘人员结识了候选人,了解了他的兴趣和动机,以便了解应考虑哪个职位。 技术性Skype面试旨在对候选人的技能进行初步评估,并消除那些肯定无法应付专职课程的人。
专职部门-主要阶段。 这是全职的部分,回答了候选人可以做什么的问题。 算法部分是专职技术部分之一。 除了算法之外,还有其他面对面的测试:例如,高级开发人员的候选人必须通过体系结构部分,未来的领导者还将回答有关管理团队和项目的问题。 通常,如果候选人在特定领域(机器学习,低级优化,高负荷系统的开发,移动开发或任何其他领域)具有某种实力,我们一定会组织一个由专业专家组成的部门。
算法部分检查候选人是否能够提出用于解决简单问题的算法,评估这些算法的复杂性并实现无错误,同时在测试质量和求解速度之间保持平衡。
为什么要在黑板或纸上写代码
程序员的自然状态是在具有语法突出显示和可跟踪性的集成开发环境中进行编程。 因此,最初在面试时在黑板或纸上写代码的想法似乎不太自然。 但是,此方法使您可以检查对于每个开发人员都非常重要的两个属性。
他们中的第一个是能够“以肉眼看”快速处理代码性能的能力。 想象一下,编写程序中出现的每个循环时,开发人员都需要花费时间尝试通过跟踪来验证其是否有效。 或当服务在生产中崩溃时,他总是需要在调试器下运行代码。 显然,即使编写和调试简单的程序也将花费他不可接受的长时间。 当然,能够通过代码审查来读取代码很有用。
第二个重要属性是事先考虑解决方案并遵循它的能力。 如果没有计划,这将导致大量的更正,删除线(在纸上)和大量代码的重写。 在现实生活中,所有这些都会极大地减慢开发速度,但是在一定程度上被代码编辑器中的工作速度所掩盖。 从这个意义上来说,纸板和纸张是无情的表面。
自然,我们考虑到手工编写代码并不太快。 因此,我们的任务通常涉及解决不超过十二行的问题,并且一个部分中需要解决的任务数量通常为两三个。
算法部分和体育节目编排
体育编程正在发展中,尤其是在未来的开发人员中,并且能够根据预定计划快速且无错误地实现简单算法的能力。 因此,具有体育编程经验的应聘者实际上在面试中的算法部分上做得很好。 通常,您会发现这样一种情况,未来的学员可以轻松应对算法部分,在15至20分钟内解决所有问题,而经验丰富的程序员则将整个小时都花在相同的任务上。
同时,编写代码的算法部分只是测试任何开发人员必需的最低技能的部分之一。 本节不仅将由奥林匹克程序员处理,还将由经验丰富的工业开发人员处理。 未来的高级开发人员或团队负责人肯定会在建筑部分等待,他将在其中展示自己的长处; 当然,本节永远不会面向学员和初级开发人员。
面试准备比赛
尤其是为了使您可以粗略地想象算法部分中给出的任务的内容,我们举办了一场比赛 ,可用于准备面试。 尝试解决所有问题,而无需运行调试器; 在记事本中编写解决方案,而不突出显示语法; 提出将通过所有测试的最短解决方案; 事先考虑所有可能的问题,并在第一时间通过解决方案。
比赛包含五个任务。 您可以尝试自己解决问题,也可以提前阅读分析:它仍然很有用,因为 您将能够训练您对先前已知算法的无错误编码的技能。
比赛任务分析任务A:宝石和珠宝
给出了两行小写拉丁字符:字符串J和字符串S。字符串J中包含的字符是“珠宝”,字符串S中包含的字符是“石头”。 有必要确定S中有多少个字符同时是“珠宝”。 简而言之,您需要检查J中有多少个S字符。
这是一个非常简单的热身任务,其中包括多种编程语言的解决方案,因此参与者可以习惯测试系统。
该算法非常简单:您需要从带有“珠宝”的行构建一个集合,然后沿着带有“石头”的行进行检查,并检查每个字符是否包含在该集合中。 尽管输入线很短,但是使用集合的这种实现来保证所得解决方案的线性复杂度,因此即使复杂度为平方的算法也可以通过。
问题B.连续单位
需要找到二进制向量中最长的单位序列并打印其长度。
解决方案算法如下:遍历数组的所有元素; 当遇到1时,需要增加当前序列长度的计数器,当遇到0时,需要重置此计数器。 最后,您需要显示计数器使用的最大值。
当阵列以所需的单位序列结尾时,请检查是否正在处理这种情况。 通过仔细实施,这种情况不需要特殊处理。
尝试仅使用固定数量的附加内存。
任务C.重复删除
给出了以非降序排列的32位整数数组。 需要从中删除所有重复项。
正确的算法顺序处理数组的元素,并将其与最后的输出进行比较。 您必须记住更新包含所显示的最后一个元素的变量,此外,在处理最后一个元素时不要犯错误。
解决此问题时,您也不需要使用额外的内存。
任务D.括号序列的生成
给定一个整数 n 。 需要打印所有正确的括号长度序列 2 cdotn 按字典顺序排序(请参阅https://ru.wikipedia.org/wiki/Lexographic_order )。 任务中仅使用括号。
这是一个相对复杂的算法问题的示例。 我们将生成一个字符序列。 在每个时刻,我们都可以为当前序列分配一个左括号或一个右括号。 如果之前添加的括号少于n个,则可以添加一个括号;如果按照当前顺序,如果括号的数量超过了括号的数量,则可以添加一个括号。 这种算法经过精心实施,可以自动保证答案中的字典顺序; 在与响应n的元素数量乘积成比例的时间内工作; 这需要线性数量的附加内存。
下面是一个无效算法的示例:我们生成所有可能的括号序列,然后仅输出那些证明正确的括号序列。 同时,答案的数量不能比上述算法更快地解决问题。
问题E.字谜
这个相当简单的任务是问题的典型示例,要解决该问题,必须使用关联数组。 在确定时,您需要考虑可以重复的字符,因此您需要使用的不是集合,而是字典。 因此,解决方案如下:我们从每一行组成一个字典,该字典将为每个字符存储其重复次数; 然后比较结果字典。 如果它们重合,则需要打印一个单位,否则-为零。
替代解决方案:对输入线进行排序,然后进行比较。 该解决方案更糟,因为它运行速度较慢并且还会更改输入。 但是此解决方案不使用额外的内存。
如果在面试中您有几种不同特征的解决方案,请告诉我们。 当开发人员知道解决问题的几种选择并可以谈论其优点和缺点时,这总是很棒的。
任务F.合并 k 排序列表
给定 k 以非降序排序的非负整数数组,每个不超过100。构建其合并结果是必需的:以非降序排序的数组,其中包含原始元素的所有元素 k 数组。 每个数组的长度不超过 10 cdotk 。
为每个数组创建一个指针; 最初,每个指针位于相应数组的开头。 我们将与指针位置相对应的元素放置在支持提取最小值的任何数据结构中-它可以是多集或例如堆。 接下来,我们将从该结构中提取最小元素,将其作为响应,将指针的位置移至相应数组中,并将该数组中的下一个元素放入数据结构中。
在此任务中,许多人难以输入格式。 请注意,这些行的第一个元素没有描述数组的元素,而是描述了数组的长度!
比赛常见问题
答: 我肯定写了正确的代码,但是测试失败了。 可能是他们的错误?
问:不,所有测试均正确。 想想:您可能没有预见到任何异常情况。
答: 我用X编写,肯定在任务Y中需要更多的内存。提高限制!
问:所有限制的设置方式都可以使用任何可用语言来解决。 尝试检查在存储限制严格的任务中是否意外读取了整个输入文件。
答: 由于所示限制,某些任务可以轻松解决。 你为什么要这样做?
问:我们专门简化了某些任务中的输入,因此,参与者可以更轻松地专注于算法的实现,而不必考虑例如下载数据的速度或体育编程中其他重要的事情。 尝试完全实施我们推荐的算法-只有在这种情况下,您才能从比赛中获得最大的收益。
答: 我不想通过比赛。 可以吗
问:当然可以! 比赛不对所有候选人都有约束力。 但是,我仍然建议解决它:在任何情况下它都将很有用。
答: 您还建议您准备什么?
问:阅读有关Yandex采访的官方页面上的提示: https : //yandex.ru/jobs/ya-interview 。 我将自己补充说,在leetcode.com上解决问题对于任何实践的开发人员都非常有用,无论他打算在不久的将来接受采访还是参加编程竞赛。 即使少量的练习,您也可以在解决工作任务时更加自信。
结论
我经常参加有关开发人员和开发经理的会议,我是许多开发聊天的成员,进行了数百次采访,并在Yandex上雇用了大量开发人员。 经验表明,在木板或纸上写代码的算法部分经常会提出问题。 最后,我将回答其中最受欢迎的问题。
为什么在与开发人员的实际工作条件截然不同的条件下进行采访?
这使您能够了解候选人是否能够在不启动调试器的情况下在程序中发现问题; 他是否可以事先提出算法计划,然后准确地遵循它; 他能否提出少量但足够的测试,然后对照这组测试检查其实现。
这样的部分是否给体育程序员带来不公平的优势?
体育编程在开发人员中培养了一些非常有用的技能,因此奥林匹克竞赛编程的参与者在算法部分确实做得很好。 因此有一个优势,但这是公平的。 算法部分只是众多部分之一,因此每个候选人都将有足够的机会展示自己的优势!
如果所有算法都已实现很长时间,而您只需要能够在现成的库中寻找它们的实现,那么为什么要进行算法部分?
在所有开发人员共有的算法部分中,我们仅测试最低限度的技能:提出有无错误的能力以实现包含循环,检查条件以及可能需要使用关联数组的简单算法。 经常编写此类代码以实现用户服务。
在不测试大量开发人员技能的部分中有什么意义?
实际上,算法部分仅检查任何开发人员所需的最少技能。 我们将在其他部分的帮助下测试其他技能。
您是否为所有专业的开发人员执行算法部分?
是的 为后端开发人员,分析师,移动和前端开发人员,基础结构和机器学习方法的开发人员等提供算法部分。