在微软做了四年面试官,分享一下刷 leetcode 的正确姿势

2020-06-10 12:26:10 +08:00
 longSwordMan

在微软作了三四年的面试官,面过几百人,早已经知道现在的小朋友喜欢刷题,自然不会傻到原原本本的去考 leetcode 的原题。所以最好不要通过死记硬背,想要碰到原题来制霸面试。

划重点:编程面试,只有高频知识点,没有所谓的高频题。

众所周知,微软以及诸多其他大厂的面试算法题主要是以 leetcode 为素材的改编,我现在分享一些面试真题以及我自己和同事作为面试官的改编思路,希望可以帮到还在苦战刷题的同学。我会将大部分的 leetcode 原题过一遍,再附上面试真题的改写思路,尽量讲得傻瓜。由于篇幅限制,在这里我只举几个小栗子,更多面试真题和改写大家可以关注我的专栏文章。

我尽量保持每周两更+回复评论,看后续的反馈情况决定是否改变更新频率以及增减分享的内容,每条评论回复都会看,也可以加微信交流:longswordMAN,注明 V2EX 的 id 即可。

————————————————————————————————————————

废话不多说,正题开始:

我们先来看 leetcode 上第 1 号问题:Two Sum:

给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。

你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9

所以返回 [0, 1]

9204 次点击
所在节点    LeetCode
77 条回复
longSwordMan
2020-06-10 12:27:45 +08:00
分析:简单题,考的是哈希表,暴力两重循环必挂。现在网上的帖子都喜欢和你说 leetcode 第 XX 题 是高频题,其实都是懒人思维,属于新手的思维误区。真正高频的是一些特定的知识点,如果按这种“原题照搬”思维,题目稍微做一些变招,大概率是要马失前蹄。

这里的真正的高频考点是数据结构哈希表,划重点:哈希表的应用面试必考,一定会以某种形式在题目的某一部出现,以后还会讲到哈希表和二叉树,哈希表和二位数组等其他数据结构结合的变招。
longSwordMan
2020-06-10 12:28:03 +08:00
面试官改编思路:
1. 不同的运算规则,可以是乘除法,可以发明一个运算规则。
真题:
给定一个整数数组和一个目标值,找出数组中乘积为目标值的两个数。

示例:

给定 nums = [2, 7, 11, 15], target = 14

因为 nums[0] * nums[1] = 2 * 7 = 14
所以返回 [0, 1]

其实换汤不换药,乘除法注意考虑边界情况即可(除以零),如果面试官自己发明的运算法:比如运算符:bla 的规则是: X 'bla' Y = X*Y - X -Y 。 同样的,查表规则改一下而已,换汤不换药,注意考虑边界情况 。
longSwordMan
2020-06-10 12:28:16 +08:00
2. 换一个数据结构,看面试者是否能够利用规则,在时间复杂度上进一步优化。

当然有序数组也可以改成二叉树等其他数据结构,或者是一些具备某特性的数据结构。有序数组的话,注意用二分查找,可以把时间复杂度降到 O ( logn ),注意哈希表的构建时间复杂度是 O ( n ),能直接用二分查找就直接用,不要考虑哈希。

真题:

给定一个“拐弯数组”,由两个有序数组拼接而成,但两数组升降序相反。 如:[1,2,3] + [6, 5, 4] ---> [1,2,3, 6, 5,4]。 要求在拐弯数组中找到给定的 target 。

这题如果用哈希,虽然是 O(n),但不是最优,没有用到数组的特性。我们先用二分法找到拐点,再到两个有序数组中二分,把复杂度优化到 O ( logn )
longSwordMan
2020-06-10 12:28:28 +08:00
3. 变成多数之和,比如 3 sum 。这样的改写容易真题:
给定一个有序整数数组和一个目标值,找出数组和为目标值的三个数。

示例:

给定 nums = [2, 7, 11, 15], target = 20

因为 nums[0] + nums[1] + nums[2] = 2 + 7 + 11 = 20
所以返回 [0, 1, 2]
longSwordMan
2020-06-10 12:28:46 +08:00
思路类似,查两次表,但注意排除第一个数,比如 2+2+2 这种一个数重复用多次的情况。

当然这都是容易的,如果三个数,再结合第 1 条变化,查表次数仍然是两次,但不要被复杂的运算搞晕,然后注意边界条件即可。

看完了这几个我出的改编面试真题,不知道看官们是否对原来的刷题方式有所改观呢?总之,没有所谓的高频题,只有高频知识点,我们刷题的同时也要勤加思考,思考背后的考察知识点,甚至可以依照我上面分享的改编思路,自己给自己出题,这样才能把刷题的效率最大化。刚才说的三类变体,本质上都是对 [哈希表] 这个知识点的考察,如果对题目本身死记硬背,而忽视知识本身,是非常低效的。那么哈希表这个数据结构的意义就在于:可以通过 O ( 1 )的时间复杂度来查找元素是否存在于集合中,而不用 O ( n )来遍历查找。

下次更新一些新的真题,着重说一些其他的哈希表的面试变招,会结合 leetcode 原题来说。
noreplay
2020-06-10 12:30:35 +08:00
等更新,收藏了
GromHellscream
2020-06-10 12:35:07 +08:00
谢谢分享,先收藏一波。
hdbzsgm
2020-06-10 12:38:04 +08:00
是这个思路 我刷题喜欢 按模块来 链表 数组 哈希 树 图 然后再看看 字符串 greedy dp dfs bfs 类似变种的题就差不多了
longSwordMan
2020-06-10 12:44:46 +08:00
@hdbzsgm 同路中人
longSwordMan
2020-06-10 12:44:58 +08:00
@hdbzsgm 握爪
basefas
2020-06-10 13:11:17 +08:00
所以说专栏呢?
also24
2020-06-10 13:19:12 +08:00
@longSwordMan #3
有序数组的话,可以直接双指针 O(n) 解决吧

[ 1, 2, 3, 5, 8, 9 ], target = 8

1+9 = 10 > 8
1+8 = 9 > 8
1+5 = 6 < 8
2+5 = 7 < 8
3+5 = 8
27
2020-06-10 13:21:31 +08:00
@also24 可以,但是也不如二分的 O(logn)快
also24
2020-06-10 13:23:19 +08:00
@longSwordMan #3
对于有序数组二分查找的方案,
因为第一个数字还是要遍历的也就是 O(n) ,
然后查询第二个数字的时候走二分查找需要 O(logn),
所以实际上总体复杂度是 O(nlogn) 吧
also24
2020-06-10 13:23:50 +08:00
@27 #13
二分查找也需要遍历第一个数字的吧,还有个 O(n) 在外面哇
eastlhu
2020-06-10 13:27:14 +08:00
期待大佬的专栏
WhyLevi
2020-06-10 14:47:39 +08:00
干货拉满
xuzywozz
2020-06-10 15:24:18 +08:00
多谢分享,收藏了
yamasa
2020-06-10 15:42:20 +08:00
马克
yamasa
2020-06-10 15:42:31 +08:00
收藏,后面学习

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/680304

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX