昨晚是头条春招的第一场笔试,结束后我们收到许多询问如何解题的信息,各大技术论坛也在热烈讨论。
So我们特意邀请出题官大神们为大家提供官方正版的解题思路,诚意满满的干货分享,不要错过哦~
本次在线笔试一共采用了四道编程题(不同方向的试卷题目略有调整),四道题覆盖了数列、字符串、数据结构等各个基础知识,分别包含纯代码实现和算法设计的题目。
Prob 1. 找出函数的最宽尖峰
正确率:1149 / 5371
题意:求给定数列 A 中先升后降的最长连续子序列,要求 O(n)。
题解:简单题。预处理 left[i] 表示以 A[i] 为结尾的连续最长上升序列长度,right[i] 表示 A[i] 为起始的连续最长下降序列长度,那么答案实际上就是 max{left[i] + right[i] - 1},更新答案时顺便记录最优区间即可。
唯一的 trick 是 left[i] > 1 和 right[i] > 1 必须同时满足,这一点在题目中已经有说明。
Prob 2. Paragraph
正确率:732 / 3732
题意:给定一个英文段落(包含 n 个句子)和 m 次查询,每次给定一个句子,求段落中相同单词数量最多的句子。各个英文句子不包含标点,大小写不敏感。
题解:做法很多,时间卡得也比较宽松。一个简单做法是对原文的各个英文句子,都预处理包含的单词集合(如果用 hash set 的话,这一步复杂度是 O(n * w))。对于每次查询,枚举句子中的单词到各个 set 中查找是否存在,随后统计出现次数取 max 即可。这样查询部分总的复杂度是 O(m * w * n)。
更快的做法是对原文出现的所有单词,通过一个 hash map 维护它们分别出现在哪些原文句子中,这个预处理的复杂度同样是 O(n * w) 的。在每次查询的时候,枚举句子中的单词,给它在原文中出现过的句子进行计数,最后在所有的计数当中取 max 即为答案。查询部分的复杂度是 O(m * (w + n)) 的。
无论是哪种做法,最重要的 trick 是各个单词的去重,防止多次计数。很多同学在代码中踩了这个坑。
Prob. 3 绘制括号序列
正确率:87 / 1655
题意:给定一个合法的括号序列,以字符矩阵的形式翻转后输出。
题解:代码实现题。先预处理每一个括号的深度,从而推出应打印的括号的大小,剩下的就是扫一遍处理下打印细节了。一个可能的 trick:注意行末不要输出多余的空格。
Prob. 4 数列
正确率:36 / 4550
题意:给定两个数列 A 和 B 以及 q 组查询 (x, y),每次求满足 A[i] >= x 且 B[i] >= y 这样的 i 的数量。
题解:暴力的 O(n * q) 的做法可以通过 30% 的数据。考虑把原先所有 (A[i], B[i]) 整数对按照 A 排序,所有查询按照 x 排序。随后从小到大扫描所有查询 (x[i], y[i]),维护一个指针 k 指向 AB 对中满足 A[k] >= x[i] 的位置。对于当前的这次查询,要求的就是所有大于 k 的位置中,满足 B[k] >= y[i] 的数量。因此我们维护一个高效支持 insert / delete / lower_bound 的数据结构来维护当前合法的 B 的值即可,满足条件的包括树状数组,平衡树等,复杂度都在 log 级别。(如果将 k 从后往前维护,可以省去 delete 操作)
总的复杂度为 O(n + qlogn)。
4月18日头条还有第二场笔试,
想要挑战的同学快登录job.toutiao.com/campus投递简历吧!