对于茫茫多的程序员来说,准备算法面试简直就是一个亚历山大的过程。看不完的学习资料,更惨的是,很多内容和程序员干的事情感觉相去甚远,这无疑只会雪上加霜。
这样的结果之一就是:程序员需要花上数周的时间在诸如LeetCode这样的在线编程平台上准备刷上几百个面试题目。这些焦虑的程序员都关心类似的问题:我刷了足够的题了吗?我应该再来点吗?
这就是为啥我专注于帮助码农们掌握每个问题背后的模式的原因:这样的话,你们就不需要苦逼哈哈地担心着茫茫多的(一千多道)LeetCode的进度条了,也帮助你们避免盲目刷题的疲劳。如果你理解这些通用的模式,你就可以把他们当做是模板,去解决其他类似的被改头换面过的题目了。
这篇文章就和大家唠唠所有的面试题目可能的14种模式。当然更重要的,我会给大家讲讲怎么去识别每种模式,每个模式再给大家来几个样题尝尝鲜。当然,这些只是冰山一角啦,详细的,不用多说,墙裂推荐你去看这门课:
Grokking the Coding Interview: Patterns for Coding Questions该课程提供详细的理论讲解,例子和编程训练。
如果你需要买该网址的任何课程,都可以使用coupon code:awesome-developer-20 拿到额外八折。
接下来的这些模式是建立在你已经知晓了数据结构的基础之上的。如果你还没掌握的话,嘿嘿,推荐你去看:
Mastering Data Structures: An interview refresher
客官,您最需要的14种模式已经就位:
1. 滑动窗口。
2. 双指针。
3. 快慢指针。
4. 区间合并。
5. 循环排序。
6. 原地反转链表。
7. 树上的BFS。
8. 树上的DFS。
9. 双堆。
10. 子集。
11. 变种二分。
12. 最大前K个元素。
13. K-路归并。
14. 拓扑排序。
我们开始吧(我是郭杰瑞既视感)!
滑动窗口类型的题目经常是用来执行数组或是链表上某个区间(窗口)上的操作。比如找最长的全为1的子数组长度。滑动窗口一般从第一个元素开始,一直往右边一个一个元素挪动。当然了,根据题目要求,我们可能有固定窗口大小的情况,也有窗口的大小变化的情况。
下面是一些我们用来判断我们可能需要上滑动窗口策略的方法:
常见的问题有:
双指针是这样的模式:两个指针朝着左右方向移动(双指针分为同向双指针和异向双指针),直到他们有一个或是两个都满足某种条件。双指针通常用在排好序的数组或是链表中寻找对子。比如,你需要去比较数组中每个元素和其他元素的关系时,你就需要用到双指针了。
我们需要双指针的原因是:如果你只用一个指针的话,你得来回跑才能在数组中找到你需要的答案。这一个指针来来回回的过程就很耗时和浪费空间了 — 这是考虑算法的复杂度分析的时候的重要概念。虽然brute force一个指针的解法可能会奏效,但时间复杂度一般会是O(n²)。在很多情况下,双指针能帮助我们找到空间或是时间复杂度更低的解。
识别使用双指针的招数:
可以放双指针大招的题目:
这种模式,有一个非常出门的名字,叫龟兔赛跑。咱们肯定都知道龟兔赛跑啦。但还是再解释一下快慢指针:这种算法的两个指针的在数组上(或是链表上,序列上)的移动速度不一样。还别说,这种方法在解决有环的链表和数组时特别有用。
通过控制指针不同的移动速度(比如在环形链表上),这种算法证明了他们肯定会相遇的。快的一个指针肯定会追上慢的一个(可以想象成跑道上面跑得快的人套圈跑得慢的人)。
咋知道需要用快慢指针模式勒?
那啥时候用快慢指针而不是上面的双指针呢?
快慢指针可秒的题目:
区间合并模式是一个用来处理有区间重叠的很高效的技术。在设计到区间的很多问题中,通常咱们需要要么判断是否有重叠,要么合并区间,如果他们重叠的话。这个模式是这么起作用的:
给两个区间,一个是a,另外一个是b。别小看就两个区间,他们之间的关系能跑出来6种情况。详细的就看图啦。
理解和识别这六种情况,灰常重要。因为这能帮你解决一大堆问题。这些问题从插入区间到优化区间合并都有。
怎么识别啥时候用合并区间模式呀?
合并区间的题目:
这种模式讲述的是一直很好玩的方法:可以用来处理数组中的数值限定在一定的区间的问题。这种模式一个个遍历数组中的元素,如果当前这个数它不在其应该在的位置的话,咱们就把它和它应该在的那个位置上的数交换一下。你可以尝试将该数放到其正确的位置上,但这复杂度就会是O(n^2)。这样的话,可能就不是最优解了。因此循环排序的优势就体现出来了。
咋鉴别这种模式?
能用循环排序解的题:
在众多问题中,题目可能需要你去翻转链表中某一段的节点。通常,要求都是你得原地翻转,就是重复使用这些已经建好的节点,而不使用额外的空间。这个时候,原地翻转模式就要发挥威力了。
这种模式每次就翻转一个节点。一般需要用到多个变量,一个变量指向头结点(下图中的current),另外一个(previous)则指向咱们刚刚处理完的那个节点。在这种固定步长的方式下,你需要先将当前节点(current)指向前一个节点(previous),再移动到下一个。同时,你需要将previous总是更新到你刚刚新鲜处理完的节点,以保证正确性。
咱们怎么去甄别这种模式呢?
这种模式的适用场景:
这种模式基于宽搜(Breadth First Search (BFS)),适用于需要遍历一颗树。借助于队列数据结构,从而能保证树的节点按照他们的层数打印出来。打印完当前层所有元素,才能执行到下一层。所有这种需要遍历树且需要一层一层遍历的问题,都能用这种模式高效解决。
这种树上的BFS模式是通过把根节点加到队列中,然后不断遍历直到队列为空。每一次循环中,我们都会把队头结点拿出来(remove),然后对其进行必要的操作。在删除每个节点的同时,其孩子节点,都会被加到队列中。
识别树上的BFS模式:
该模式可解的题:
树形DFS基于深搜(Depth First Search (DFS))技术来实现树的遍历。
咱们可以用递归(或是显示栈,如果你想用迭代方式的话)来记录遍历过程中访问过的父节点。
该模式的运行方式是从根节点开始,如果该节点不是叶子节点,我们需要干三件事:
识别树形DFS:
树形DFS可破的题目:
很多问题中,我们被告知,我们拿到一大把可以分成两队的数字。为了解决这个问题,我们感兴趣的是,怎么把数字分成两半?使得:小的数字都放在一起,大的放在另外一半。双堆模式就能高效解决此类问题。
正如名字所示,该模式用到了两个堆,是不是很难猜?一个最小堆用来找最小元素;一个最大堆,拿到最大元素。这种模式将一半的元素放在最大堆中,这样你可以从这一堆中秒找到最大元素。同理,把剩下一半丢到最小堆中,O(1)时间找到他们中的最小元素。通过这样的方式,这一大堆元素的中位数就可以从两个堆的堆顶拿到数字,从而计算出来。
判断双堆模式的秘诀:
典型问题:
超级多的编程面试问题都会涉及到排列和组合问题。子集问题模式讲的是用BFS来处理这些问题。
这个模式是这样的:
给一组数字 [1, 5, 3]
该模式的详细步骤如下:
如果判断这种子集模式:
子集模式适用的场景:
当你需要解决的问题的输入是排好序的数组,链表,或是排好序的矩阵,要求咱们寻找某些特定元素。这个时候的不二选择就是二分搜索。这种模式是一种超级牛的用二分来解决问题的方式。
对于一组满足上升排列的数集来说,这种模式的步骤是这样的:
图示该过程的话,如下图所示:
变种二分可以解决的问题:
任何让我们求解最大/最小/最频繁的K个元素的题,都遵循这种模式。
用来记录这种前K类型的最佳数据结构就是堆了(译者注:在Java中,改了个名,叫优先队列(PriorityQueue))。这种模式借助堆来解决很多这种前K个数值的问题。
这个模式是这样的:
注意这种模式下,咱们不需要去排序数组,因为堆具有这种良好的局部有序性,这对咱们需要解决问题就够了。
识别最大K个元素模式:
前K个元素模式的场景:
K路归并能帮咱们解决那些涉及到多组排好序的数组的问题。
每当你的输入是K个排好序的数组,你就可以用堆来高效顺序遍历其中所有数组的所有元素。你可以将每个数组中最小的一个元素加入到最小堆中,从而得到全局最小值。当我们拿到这个全局最小值之后,再从该元素所在的数组里取出其后面紧挨着的元素,加入堆。如此往复直到处理完所有的元素。
该模式是这样的运行的:
识别K路归并:
K路归并的题目:
拓扑排序模式用来寻找一种线性的顺序,这些元素之间具有依懒性。比如,如果事件B依赖于事件A,那A在拓扑排序顺序中排在B的前面。
这种模式定义了一种简单方式来理解拓扑排序这种技术。
这种模式是这样奏效的:
拓扑排序模式识别:
拓扑排序的试炼场:
刷LeetCode崩溃了吗?来学习这14种屠龙模式吧,你将会对解决任何一个算法问题有更全面的认知。
如果你想进一步了解这些模式,以及对每种模式下的题目有哪些感兴趣的话,请移步这个这里:
Grokking the Coding Interview: Patterns for Coding Questions这个是秒杀算法系列的最新课程,还别说,超过两万人通过他们找到了大公司的工作。
这门课问能给出的最高支持就是,我是真的好希望我准备面试的时候有这门课。
Again,如果你需要买该网址的任何课程,都可以使用折扣码:awesome-developer-20 拿到额外八折。
11.16.2019更新译者注:在本文的配套课程中其实包含了动态规划(DP),但这篇文章的Medium原文并没有提及DP,为了尊重原文,这里也就写14种了。个人猜测是他们家有单独的DP课,所以就没把DP写到这篇文章里面了。
DP相关的内容可以参考:
穷码农:动态规划及面试,学完这一篇,你就入门了:Dynamic Programming, 动态规划,经典题目谢谢读者大王的评论。
本文翻译自:
https://medium.com/hackernoon/14-patterns-to-ace-any-coding-interview-question-c5bb3357f6ed
原文:https://www.cnblogs.com/qiongmanong/p/12159299.html