写在前面的话
这两年因为疫情以及种种原因吧,互联网的大环境明显不比前几年了,尤其是去年后半年到今年前半年,各个社区、群聊,猎头那边都充满了裁员、大厂HC锁定的消息。似乎以前外面一直都有坑,随时随地可以提桶跑路的大环境都没有了。有一份固定的工作,公司不裁员,车加的起油,房贷能还上,似乎都要感恩戴德了。
时间来到6、7月份,好像春风又吹拂了大地,市场好像回暖了。开始有猎头朋友不停的在Call介绍国内的一些独角兽,或者是海外的一些岗位,如亚马逊、虾皮等。
终究是架不住好友的多次拉扯,去面试了抖音某部门,为了避免尴尬就不说是那个具体部门了。
面试过程
一面、二面没啥特别的,大多都是前端程序员必备基础知识:
- HTTP2相关;
- 网络缓存(强缓存和协商缓存);
- EventLoop(浏览器和Node.js区别);
- 多端适配方案;
- 手写Promise;
- 手写EventEmitter;
- 小程序开发经验;
还有些其他的问题,也都是常见的,记不太清了。
顺带要点赞下线上面试系统,不用大老远的跑过去。甚是好!
三面:
三面整体感觉难度加深许多,深入的聊了些项目架构、主R视角、项目推动落地。
重点1:项目中做的性能优化策略以及收益(前后关键性指标对比,如TTL、LCP、FMP等)。
在这里要着重提醒各位,如果你做了性能优化,在做之前和做之后一定要确定参考性指标,前后数据的收集,非常重要!!!
重点2:社区开源项目、社区影响力
在这里再着重推荐一下,胡哥搞的零成本式路由权限解决方案的react-router-middleware-plus
。
NPM地址
GitHub地址
欢迎大家Star
和PR
,一起为开源社区做贡献吧!
重点3:宇宙条的经典特色 HARD难度的算法题: 求滑动窗口的最大值!!!LeetCode原题点这里
题目要求:
给定一个数组 nums
和滑动窗口的大小 k
,请找出所有滑动窗口里的最大值。
这个提供大家一个套路面试官的攻略,让他逐步看到你解决问题的能力以及整个过程的思考。
这道HARD难度的问题,提供两个思路,由浅入深来看。
首先在看到这道题的时候,你可以直接快速的说出双层循环
的方法,依次比较范围内的最大值,最终得出结果。
附上解题思路:
function maxSlidingWindow(nums: number[], k: number): number[] {
// 缓存数组的长度
const len = nums.length;
// 定义存储最大值的数组
const res: number[] = [];
// 临界点判定
if (len === 0) {
return res;
}
// 外层循环,控制起点位置,注意结束点索引的临界条件是len - k + 1
for (let i = 0; i < len - k + 1; i++) {
// 每次都初始化最大值
let max = -Infinity;
// 判断从当前位置开始的k个数中的最大值
for (let j = i; j < i + k; j++) {
if (nums[j] > max) {
max = nums[j]
}
}
// 每次将最大值放入数组中
res.push(max);
// 下次开启循环的时候,相当于从下一个新的起点开始了
是可以得到结果,但是性能相当的不理想呀!
停顿一下,在等面试官内心稍微想嘲讽你的时候,你再说出来,这种方式的算法复杂度是,性能不理想,肯定不是我们想要的。提出第二种算法复杂度为
的方案。
在上面的实现中,相对于每次起点的值,都执行了k
次判断,是没有必要的。
双端队列实现
我们知道队列具有“先进先出”的特点,而双端队列呢,是支持在队头和队尾都支持元素进队、出队操作。
假定我们维护一个队列,在队列的首位一致记录当前k
个元素的最大值;
如果新出现的值比队尾的值小,则进行进队操作;
如果新出现的值比当前队尾的值大,则从队尾开始依次进行出队操作,知道前一个值比当前值大;
每次向前走一步,则队头元素要进行移除操作。
附上解题思路:
function maxSlidingWindow(nums: number[], k: number): number[] {
// 缓存数组长度
const len = nums.length;
// 存储结果
const res: number[] = [];
// 设置队列,队列中存储索引,便于计算k范围
const queue = [];
// 遍历元素
for (let i = 0; i < len; i++) {
// 首先判断队尾元素与当前值nums[i]的比对
while (queue.length && nums[queue[queue.length - 1]] < nums[i]) {
// 进行出队操作
queue.pop();
}
// 将当前值放入,注意是索引
queue.push(i);
// 当队首元素索引与当前索引i的差值>=k时,需要将队首元素移除,说明这个范围已经过了k个元素了
if(queue.length && queue[0] <= i - k) {
// 队首元素移除
queue.shift();
}
// 什么时候开始取值呢,只要开始满足有k个数之后,就可以取值了
if (i >= k - 1) {
res.push(nums[queue[0]])
}
}
// 返回结果
return
对于数组nums
中的元素,都是经历了一次入队、一次出队操作。每次取滑动窗口中元素的最大值时,都是直接取的queue
的队首元素。实际的算法复杂度就是。
此时此刻,你和面试官内心都是非常开心的。面试官心中感叹茫茫人海中我又遇到了一个好苗子!你内心就可以窃喜今年薪资是不是又有double的机会了。
最后
如果后面有合适的,可以更新的,也会写下来。
大家可以蹲个坑!