一个朋友是前阿里人,37岁,离职后就职美团。以前投一个面一个,今年想跳槽,但没想到投十个能有两个面试机会就不错了,最后索性又回了阿里做架构。
他在面试的时候,碰见比自己大的面试官,态度和善,一般面试都能过。而如果碰到比自己小很多的面试官,能给你从天上问到地下,好像在说,就这?你也能不会?
我同事的说法:他跟你能不能和得来,年龄是硬伤。但凡你要在他手下干活,年龄又相差较大的话,他一般是不会要的,根本原因就是怕管不住。
另外几个朋友,都走的技术管理岗,也35了,有的在网易,有的在滴滴。据他们说,到了这个年纪,就不要想着跳了,找一家合拍的公司好好干吧,自己混个高点的职位,出去好要价,高不成低不就的,同样没人要。
你真的以为裁员裁的是年龄大、股票多的那些人?毕业后同学朋友在华为的也有几个,据他们的说法:人家裁的都是工作十来年,考评普通职级一般,收入和股票都偏低的一群人。也就是:这部分人的工作具有可替代性。
正文
我们今天将说明以下 14 种模式:
1.滑动窗口
2.二指针或迭代器
3.快速和慢速指针或迭代器
4.合并区间
5.循环排序
6.原地反转链表
7.树的宽度优先搜索(Tree BFS)
8.树的深度优先搜索(Tree DFS)
9.Two Heaps
10.子集
11.经过修改的二叉搜索
12. 前 K 个元素
13. K 路合并
14.拓扑排序
我们开始吧!
1.滑动窗口
滑动窗口模式是用于在给定数组或链表的特定窗口大小上执行所需的操作,比如寻找包含所有 1 的最长子数组。从第一个元素开始滑动窗口并逐个元素地向右滑,并根据你所求解的问题调整窗口的长度。在某些情况下窗口大小会保持恒定,在其它情况下窗口大小会增大或减小。
下面是一些你可以用来确定给定问题可能需要滑动窗口的方法:
- 问题的输入是一种线性数据结构,比如链表、数组或字符串
- 你被要求查找最长/最短的子字符串、子数组或所需的值
你可以使用滑动窗口模式处理的常见问题:
- 大小为 K 的子数组的最大和(简单)
- 带有 K 个不同字符的最长子字符串(中等)
- 寻找字符相同但排序不一样的字符串(困难)
2.二指针或迭代器
二指针(Two Pointers)是这样一种模式:两个指针以一前一后的模式在数据结构中迭代,直到一个或两个指针达到某种特定条件。二指针通常在排序数组或链表中搜索配对时很有用;比如当你必须将一个数组的每个元素与其它元素做比较时。
二指针是很有用的,因为如果只有一个指针,你必须继续在数组中循环回来才能找到答案。这种使用单个迭代器进行来回在时间和空间复杂度上都很低效——这个概念被称为「渐进分析(asymptotic analysis)」。尽管使用 1 个指针进行暴力搜索或简单普通的解决方案也有效果,但这会沿 O(n²) 线得到一些东西。在很多情况中,二指针有助于你寻找有更好空间或运行时间复杂度的解决方案。
用于识别使用二指针的时机的方法:
- 可用于你要处理排序数组(或链接列表)并需要查找满足某些约束的一组元素的问题
- 数组中的元素集是配对、三元组甚至子数组
下面是一些满足二指针模式的问题:
- 求一个排序数组的平方(简单)
- 求总和为零的三元组(中等)
- 比较包含回退(backspace)的字符串(中等)
3.快速和慢速指针
快速和慢速指针方法也被称为 Hare & Tortoise 算法,该算法会使用两个在数组(或序列/链表)中以不同速度移动的指针。该方法在处理循环链表或数组时非常有用。
通过以不同的速度进行移动(比如在一个循环链表中),该算法证明这两个指针注定会相遇。只要这两个指针在同一个循环中,快速指针就会追赶上慢速指针。
如何判别使用快速和慢速模式的时机?
- 处理链表或数组中的循环的问题
- 当你需要知道特定元素的位置或链表的总长度时
何时应该优先选择这种方法,而不是上面提到的二指针方法?
- 有些情况不适合使用二指针方法,比如在不能反向移动的单链接链表中。使用快速和慢速模式的一个案例是当你想要确定一个链表是否为回文(palindrome)时。
下面是一些满足快速和慢速指针模式的问题:
- 链表循环(简单)
- 回文链表(中等)
- 环形数组中的循环(困难)
4.合并区间
合并区间模式是一种处理重叠区间的有效技术。在很多涉及区间的问题中,你既需要找到重叠的区间,也需要在这些区间重叠时合并它们。该模式的工作方式为:
给定两个区间(a 和 b),这两个区间有 6 种不同的互相关联的方式:
理解并识别这六种情况有助于你求解范围广泛的问题,从插入区间到优化区间合并等。
那么如何确定何时该使用合并区间模式呢?
- 如果你被要求得到一个仅含互斥区间的列表
- 如果你听到了术语「重叠区间(overlapping intervals)」
合并区间模式的问题:
- 区间交叉(中等)
- 最大 CPU 负载(困难)
5. 循环排序
这一模式描述了一种有趣的方法,处理的是涉及包含给定范围内数值的数组的问题。循环排序模式一次会在数组上迭代一个数值,如果所迭代的当前数值不在正确的索引处,就将其与其正确索引处的数值交换。你可以尝试替换其正确索引处的数值,但这会带来 O(n^2) 的复杂度,这不是最优的,因此要用循环排序模式。
如何识别这种模式?
- 涉及数值在给定范围内的排序数组的问题
- 如果问题要求你在一个排序/旋转的数组中找到缺失值/重复值/最小值
循环排序模式的问题:
- 找到缺失值(简单)
- 找到最小的缺失的正数值(中等)
6.原地反转链表
在很多问题中,你可能会被要求反转一个链表中一组节点之间的链接。通常而言,你需要原地完成这一任务,即使用已有的节点对象且不占用额外的内存。这就是这个模式的用武之地。该模式会从一个指向链表头的变量(current)开始一次反转一个节点,然后一个变量(previous)将指向已经处理过的前一个节点。以锁步的方式,在移动到下一个节点之前将其指向前一个节点,可实现对当前节点的反转。另外,也将更新变量「previous」,使其总是指向已经处理过的前一个节点。
最后,面试前该准备哪些资源复习?
其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
这里再分享一下我面试期间的复习路线:(以下体系的复习资料是我从各路大佬收集整理好的)
《Android开发七大模块核心知识笔记》
《960全网最全Android开发笔记》
《379页Android开发面试宝典》
历时半年,我们整理了这份市面上最全面的安卓面试题解析大全
包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。
《507页Android开发相关源码解析》
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。
通过前两轮技术面试的几率。
《507页Android开发相关源码解析》
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。
资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图,戳这里免费领取