前言
面经我们也看过分享过,但反向面经真的不多见,来看看大佬是怎么反套路的!
对了,文末还有为大家准备的彩蛋✨,建议「戴上耳机」品鉴~
当你在面试中手撕算法时,会不会有这样的情况:
- 审题比周赛还快,面试官话音刚落,你就迫不及待敲起了代码。
- 人狠话不多,写代码的时候静悄悄,全世界只能听见清脆的键盘声。
- 一旦思路走不通,表面强装淡定,但暗自着急,内心独自枯萎。
如果上述的情形戳中了你,那么恭喜你即将探索面试中的新的隐藏技能
——利用好你的面试官!简称“反向面试”!
学会这点,让你无痛提升面试水平,用崭新的视角来看待技术面。
本文分成两个部分:
心法篇:
- 分析技术面试的底层逻辑,讲清“反向面试”的动机和意义
实战篇:
- 保姆级教学面试方法论,对于面试中的各个环节逐步拆解!
面试心法
心法一:技术面试不仅是考察技术
不少朋友把全部的注意力都放在刷题上,一心争取面试中全部ace。
这样的努力当然是值得夸夸的,但是遗憾的是,在实际的面试中,“做出题目”和“面试通过”并不能直接画等号。
面试更像是一场全方位的考量:
- 代码写的正不正确、优不优美,体现的是技术能力;
- 清晰地阐述解题思路,分析复杂度,体现的是解决问题的能力;
- 跟面试官保持良好的互动,体现的是沟通能力和团队协作精神……
面试的底层逻辑是寻找高匹配、高潜力的优秀人才。
在校招场景中,大家经验相对都薄弱,而企业也愿意培养新人,所以展现出自己的潜力就更加重要。
也许你并没有写出完美的代码,但是如果你展现出严谨的逻辑思维,训练有素的解题思路,从容自信的态度,对技术深深的热爱(热情不够,演技来凑!),跟面试官保持顺畅沟通…说不定也会深深打动 ta!
心法二:面试是一场双向奔赴
说完了技术面试的选人标准,那我们该如何展现出这些能力呢?这就要提到我们的工具人——面试官!跟独自刷题不同,面试是一场两个人的电影,充满了互动性和主观性。
面试官是一把双刃剑(面试官:是谁物化我),利用的好就是你的 offer 小助手,利用不好就是感谢信问候。
- 普通码农眼里的面试官:考验我、为难我、威慑我的敌军!
- 高端码农眼里的面试官:一起完成精彩面试的队友!
大家就想象面试官是辅助你通关的角色,在面试的全过程都要注重跟 ta 的交流互动,让他感知到你的优秀!具体的做法在后面第二部分展开讲。
心法三:熟能生巧 Practice Makes Perfect
无论对于任何岗位,短期提升面试水平的最有效的方法,就是模拟面试。
技术岗也不例外,尤其是对于刷题还不错,但一到面试就紧张做不出来的同学,那请您务必模拟面试走起!
对于模拟面试,大家可能有些疑问。
Q1:自己一个人可以模拟面试吗?
A1:当然可以!就像学英语一样,如果没有小伙伴陪你练习,那么自己建立全英的环境也是不错的选择。假装面试官 is watching you,你每次做题前就开启自言自语模式,确认自己的思路,写代码时也边写边讲解(划重点!这点是关键!),写完代码再讲一遍思路、分析复杂度。也许一开始有点奇怪,练习多了就适应这种方式了!
Q2:模拟面试需要注意什么呢?
A2:越贴近实际面试场景越好。不是做道某公司的真题就算模面了,而应该重视起来真实面试遇到的时间限制、follow-up questions、双向沟通 这些元素。再强调一下双向沟通的重要性,因为对于大多数人来说,写代码时讲话难免会影响思路,所以模面一定要刻意练习。
另一点就是注意复盘总结。你可以对面试/模面进行录音、录屏,事后来给自己各方面的能力表现进行打分,不断臻于完美。
Q3:模面好无聊,还有比模面更简单的方法吗?
A3:那就看别人的模拟面试吧~ 油管有许多资源的,就当刷剧一样看。以他人为镜,总结别人面试的亮点和问题,也是很好的学习和反思的方法。
我记得我两年前看到过 william(某计算机天才帅哥 qwq)的模面视频,真的被震撼了,他不仅是世界顶级的竞赛选手,而且他把自己的思路讲得非常清晰(这道题蛮难的,但他竟然教会了我 orz)。我也是从此把 william 当做榜样,练习这样的面试风格。
实践教学
我们正式进入实战篇,跟大家分享面试的全流程中,那些心机的沟通小技巧。
我们以一道经典的面试题 15. 三数之和 为例。
题目如下:
给你一个包含 n 个整数的数组 nums。判断 nums 中是否存在三个元素 a,b,c ,使得 a b c = 0 ?请你找出所有和为 0 且不重复的三元组。
互动一:问清题目 Ask Clarifying Questions
不要着急直接做题哦,推荐按照以下几个步骤进行。
Step 1:确定自己读懂题目。
这点非常关键,尽管面试题一般不会很难懂,但万一真理解错题意,写到一半儿才发现,不仅浪费时间,而且在面试官心中也超级减分。
如果你需要面试官的帮助,你可以大胆发问:
- “题目中的 xxx 我有些不理解,您可以具体解释一下吗”
- “请问能不能举个简单的例子呢,我想确认一下我是不是理解正确^ ^”
- “我大概明白题目了,我确认一下,假如输入是 xxxx,经过 blablabla,输出应该是 yyyy 对吗”
总之,不用担心会显得很笨哦(当然,问问题的前提是自己思考过)。
Step 2:确认输入输出格式、边界条件等细节。
我们平时做题的时候,题面都是很清楚全面的,而在面试中可能是简化版。我们需要挖掘题目中被忽略的地方,跟面试官确认。
可以问哪些问题呢?以 T15 为例,我们可以询问:
- 我们是返回三元组的个数,还是返回三元组本身呢?
- 这些三元组以什么形式返回呢?二维数组可以嘛?
- 如果不存在这样的三元组,是返回一个空数组吗?
- 返回的三元组顺序有要求吗?
- a,b,c可以为同一索引的值吗?
根据实际情况,向面试官适度问些这样的问题。意义:
- 进一步帮助自己理解题目
- 稍后写代码时会更注意细节
- 向面试官体现自己的严谨和专业度
互动二:确认思路 Explain Your Thoughts
读懂题之后就开始写代码了吗?大写的 NO!
最稳妥的做法是:先确定解题思路,了然于心再动手敲代码。而不是走一步看一步,幻想山重水复疑无路
Step 1:先分析暴力法等其他明显非最优解法。
依然是 T15,在我开始想思路之前,我会先跟面试官说:
- “这道题最容易想到的方法是暴力法,遍历所有的 a、b、c 组合,判断每个组合下是否相加为零。因为是三重循环,时间复杂度是 O(n^3),空间复杂度是 O(1)。”
然后过渡一下:
- “暴力法做了一些冗余的比较,比如 blablabla(举个例子),所以应该有更优的解法(也可以直接点明有 O(n^2) 的解法)。”
只是一个小示例。如果是有 3 种解法的题目,也可以把每种解法和相应的复杂度都简述一遍,最后实现最优的,或者是面试官指定实现某个解法。
可能你会疑惑,讲这些非最佳方法真的有用吗?
- 对自己而言,能帮助自己确定复杂度的上界。同时,发现暴力解法中的弱点,有助于提供思路。
- 对面试官而言,让他一开始就看到你的解决问题的能力、表达能力和复杂度分析能力!成功引起他的注意,让他后面认真听你讲话,不会走神!
Step 2:思考更优思路
情况 1:如果题目非常陌生,一时半会儿没有想法,需要冷静思考,那么千万别直接沉默,否则会寂静的尴尬。
记住,我们可是要引领面试官的,时刻展现我们爱沟通爱协作的个人魅力。
你可以说:
- “我可以先自己想一下吗?梳理好思路后再跟您沟通。”
- “我有个大概的思路,但需要再思考一下,您稍等我一下可以吗?”
然后你就礼貌地赢得了短暂的沉默权!
情况 2:已经有初步的想法思路了,无论是自己是否确定,都可以跟面试官先交流着。
继续 T15,假如我已经想到用双指针了,尽管我还没思考“重复”怎么处理,但是没关系,先在整体思路上跟面试达成共识。
我会说:
- “我觉得这道题可以用双指针来解决。首先对数组排序,这是对本题使用双指针的前提。遍历元素 a,其他两个 b、c 元素使用相向双指针来确定。初始化b在a的后一位,c 在数组最后一位,比较 a b c 与 0 的关系,如果小于 0,那么 b 右移,如果大于 0,那么 c 左移,直到 b、c 重合。”
还记得吗?面试官是我们的队友,不是对手。现在就是 ta 发挥价值的地方啦。
跟面试官对齐方法,可以引导面试官进入我们的思考过程,跟着我们的节奏走。只有充分明白我们的思路,才能更好地帮助我们。
具体有哪些帮助呢?
- 如果我们有没考虑周全的地方,面试官会提醒我们,比如这道题,面试官可能会问“那你怎么保证三元组不重复呢”。
- 如果我们整个思路就是错误的,面试官会及时把我们拉回来的,有可能直接指出来,有可能给你个用例让你自己发现方法行不通。
- 如果我的思路不是他想要的,他可能会说“我明白你的方法了,不过还有更优的解法,你可以再想想”。这样也很好,实时了解面试官的想法,不会浪费时间。
- 如果我们思路无敌正确,面试官一般会给出比较正面的回复,也可能比较委婉,比如“听起来没有什么问题”,“那你代码实现一下吧”。
Step 3:举个用例,用自己的解法走一遍
尽管我们已经描述思路了,但是大部分题目单讲思路会很抽象。为了确保面试官明白我的思路,我再会找简单的例子,用我的解法来给 ta 过一遍。
你认为跑测试用例是代码就位后的环节?不是的,真正心机的人还没写代码就过用例了!
我一般是边讲边在 IDE 里写注释,亲测非常专业。遇到树图的问题,最好也提前准备好画图工具,边画边举例。
继续 T15 的例子,讲述完双指针的思路后,我会说:
- “我举个例子吧,假设我们有个数组,数组元素是 -1, -1, 0, 1, 2…”,
边说边在 IDE 里敲下(python):
# nums = [-1,-1,0,1,2]
“初始化 a 是第 0 个元素,为 -1;b 是 -1;c 是 2。此时相加正好是 0”,我加了一行表头 a,b,c,例子呢就跟表头对齐。
# nums = [-1,-1,0,1,2]
# a, b, c
# -1, -1, 2 = 0
“这时候移 b 移 c 都行,那我就把 b 右移一位吧,得到 -1,0,2,相加是 1,大于 0。”边说我又加了一行。
# nums = [-1,-1,0,1,2]
# a, b, c
# -1, -1, 2 = 0, so b ->
# -1, 0, 2 > 0, so c <-
后面不再展开分析了,总之是借助 IDE 来清晰地展现出自己的解题思路。注意控制时间,例子中体现思路就可以,不一定解出答案。
这时候面试官不仅彻底懂你思路了,还可能对你印象很深刻呢。
如果举例这一步也没什么问题,那就开始写!代!码!
互动三:边写边说 Talk While You Code
到了写代码的环节,如果你静悄悄地一言不发,面试官也不晓得你在写什么,ta 可能很快就开小差了…不!我们要让他全神贯注,一整个拿捏住!
平时练习的“边说边写”就派上用场了对不对。假设你就是编程老师,面试官就是你的学生,你要实时地跟他讲解代码,带动他一起思考。
继续 T15,我开始敲代码了,我边打字边解释:
- “我们先定义一个函数,不妨叫做 threeSum 吧,输入是一个数组,输出是二维数组…”,
此时 IDE 中已经敲下了↓
def threeSum(nums: List[int]) -> List[List[int]]:
我们继续:
- “首先,我们将数组排个序,这步是 O(nlogn) 的复杂度…”
我习惯每个模块都阶段性总结一下复杂度,顺带就标在注释里了。也可以先不提复杂度,最后统一分析。
def threeSum(nums: List[int]) -> List[List[int]]:
# step1: sort,O(nlogn)
nums = sorted(nums)
当我定义变量的时候,向面试官解释一下变量的含义。比如:
“我们建立 res 数组,用来存放结果”“下面开始遍历 a,指针 i 指向的位置就是 a”
def threeSum(nums: List[int]) -> List[List[int]]:
# step1: sort,O(nlogn)
nums = sorted(nums)
# step2: two pointers
res = []
for i in range(len(nums)):
我们写 if、while 这样的语块前,也宏观地预告一下我们要做什么。比如:
- “接下来我会比较三数之和与 0 的关系,可能是大于 0,小于 0,等于 0 这三种情况”。
说着边敲下这样的 if-else 分支,给面试官一种大局观的 feel。
j, k = i 1, len(nums)-1
while j < k:
if nums[i] nums[j] nums[k] > 0:
...
elif nums[i] nums[j] nums[k] < 0:
...
else:
...
以上的举例是想展示一下该如何边写代码边讲解思路,大家也可以根据自己的风格调整措词表达。
- 朋友们,边说边写真的是神仙面试方法
- 面试官能跟着你的思路走,了解我们的思考过程。
- 当我们思路卡顿的时候,因为面试官跟上我们了,ta 可以给予适当的提示(因为他知道这道题的解法呀!)。这也就是我们强调的“利用”面试官。
- 当我们沉浸写代码的时候,可能会有一些自己没留意的简单语法错误和逻辑错误,面试官作为旁观者,会及时提醒纠正。这样的话,不至于等到最后跑用例 error 时再找 bug 在哪里。另外,即使最后运行的时候报错,面试官都不好意思给你减分,因为他全程跟着你的思路而他也没看出来!
从此写代码时养成自言自语的好习惯 OK?
互动四:总结分析 Summarize and Analyze
代码写完之后,记得做两件事:
- 有始有终,整体再简述一遍代码思路。用鼠标引导着面试官视线,简单介绍写的每个模块做了什么事情。
- 分析复杂度。分析每个步骤的时间复杂度是多少,最终整个方法的时间复杂度。还有空间复杂度是多少。
如果在总结环节,你突然意识到自己思路绕弯了,或者代码写的不简洁,也请主动跟面试官分享:
- “我发现 xx 部分想复杂了,我觉得 xxx 这样做可能更清楚”。
面试官心里也是加分的,他会觉得你很爱思考,可能是面试紧张,你原本的实力会更高。
最后,面试官可能要求跑几个他指定的用例,顺利的话就结束这场撕题,或者进入到 follow-up questions 了。即使测试结果不对,也不用着急,因为按照上述的方法走下来,代码应该没有太大问题,而且我们的表现一直很好,可能有些细节没注意到。耐心地顺着自己思路,寻找出错的原因就好了。
写在结尾
以上就是一些个人的小经验。本文的初衷是我发现不少同学不太重视面试中的沟通交流,所以来分享我的 tips。当然,我们不能舍本逐末,过于追求这些软实力,而忽视了技术实力的打磨。
如果有不同的想法,也欢迎在评论区理性讨论~
BY /
本文作者:coldme
声明:本文归“力扣”版权所有,如需转载请联系。
,