今天想分享的是一位来自读者投稿字节的面试记录(校招面经)。
首发内容来自掘金,读者小K,和他接触后才发现,他是大专,学历跟我差不多, 本科学历,求职的艰辛我都明白。
好在他十分努力,最后拿下滴滴offer,真的挺不容易的。
替他高兴,终于卷进大厂啦,希望我的读者早日进入心仪的公司。
我们聊的还不错,在某些方面上,我们达成了共识。
他说过:
虽然这一路挺艰辛,也不知道自己下一步是迈向哪里,但是在心态和技术上让我成长了很多,回头看来我还算是挺幸运的吧。
共勉!!!
点赞超过50的话,后续更新他的求职经历!!!
这个面试机会来的挺意外的,先在 Boss 投递的简历,后再牛客网看到了内推人的微信,加了微信问了下进度,挂了。
内推人给我打电话根据简历简单询问了一下情况(内推人很谦逊,毕业于一所 211 大学,和我说他的学历也很一般),然后和 hr 沟通捞了我一下,才有的这个面试机会,太感谢了。
6 月 9 日 16:00
自我介绍
怪异盒模型和标准盒模型的区别
如何触发 BFC
垂直水平居中
你了解得数组遍历方式有哪些,你觉得那个性能最优那
this 指向谁,如何更改 this 的指向
// 非原题 非原题 非原题
const o1 = {
text: 'o1',
fn: function() {
return
this.text;
}
}
const o2 = {
text: 'o2',
fn: o1.fn
}
console.log(o2.fn());
你常用的 React Hooks 有哪些,描述功能
服务端渲染了解吗 和 SPA(单页面应用) 的区别
Commonjs 和 ES6 Module 得区别
算法题
反问
大概 45 分钟吧
说一面就给我过了,等会 17:00 二面
讲讲项目,说说你的亮点
有写过 webpack 的 plugins 吗
看代码,css 选择器权重
算法:二叉树
有这么一个数据结构:
const data = [
{
"id": "1",
"sub": [
{
"id": "2",
"sub": [
{
"id": "3",
"sub": null
},
{
"id": "4",
"sub": [
{
"id": "6",
"sub": null
}
]
},
{
"id": "5",
"sub": null
}
]
}
]
},
{
"id": "7",
"sub": [
{
"id": "8",
"sub": [
{
"id": "9",
"sub": null
}
]
}
]
},
{
"id": "10",
"sub": null
}
]
现在给定一个id,要求实现一个函数
findPath(data, id) {
}
返回给定id在 data 里的路径
示例:
id = "1" => ["1"]
id = "9" => ["7", "8", "9"]
id = "100"=> []
PS: id 全局唯一,无序
说下 EventLoop
看代码
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
// 注意:这里如果返回 Promise 的话执行顺序就不一样了
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
大概 40 分钟吧,等会 18:00 三面
自我介绍
几几年的
哪里人啊
高考是出现了什么状况吗
这个学历对你产生了多少影响
还是聊聊技术吧,给一个场景,二分查找
// 当时用的 js,用 ts 只是为了表达的更清晰一点
interface Barrage {
time: Number;
barrage: String;
}
const binarySearch = (arr: Barrage[], time: number) => {
let l = 0;
let r = arr.length - 1;
while (l <= r) {
const mid = (l + r) / 2;
if (arr[mid].time === time) {
return arr[mid].barrage;
} else if (arr[mid].time < time) {
l = mid + 1;
} else {
r = mid - 1;
}
}
return null;
}
一个异步任务调度器,最多同时执行两个异步任务
为什么学前端
一个用户活跃度几千万的网站你会做哪些优化
反问
每轮面试官问的问题都很开放,引导你自己说,再根据你所说的东西再去问一些问题 连着三面,因为三面比较惨所以对其他两面问题印象不是很深
异步任务调度器
这个异步任务调度器调用机制实际和 Proimse 的 reslove 触发 then 方法是相同的,reslove 内的执行逻辑需异步触发,等待 then 方法中的内容执行完(存储好)再触发,只是方法内部执行逻辑有细微的差异而已。
二分查找
// 这除出来可有可能是个分数啊
const mid = (l + r) / 2; // Math.floor((l + r) / 2);
// l + r 也可能超出数字范围
const mid = l + Math.floor((r - l) / 2);
这心一下就哇凉哇凉的,之前的 Promise 白手写了,索引还不取整,脑袋跟进了水一样,灌得满满的那种。
第二天下午,hr 和我说面试通过,但因学历 offer 审批有些困难,会努力帮我争取。很感谢,说实话能得到这个认可,我已经很开心了。三月一开始投递简历到现在,大专不要,必须本科,学历不符,BOSS 上投递大多回复都没有,大多的公司面试机会都没有,学历问题的我也早已经习惯了。
6月15日,收到 hr 通知,最终还是不行...
不过 hr 在他们的群里发了一下,我被另一个部门又捞起来了
6 月 17 日
1 小时零 5 分(还有其他的想不起来了)
看代码,变量提升,块级作用域
算法:回文字符串(这个问题好常见),判断一个字符串最多只删1个字符,是否能成为一个回文字符串
let str = "ABCDABA"
let l = 0;
let r = str.length - 1;
const reverse = (str) => {
let temp = '';
for(let i = 0; i < str.length; i++) {
temp += str[i];
}
return temp === str;
}
const isSymmetry = (str) => {
let l = 0;
let r = str.legnth - 1;
while(l <= r) {
if(str[l] === str[r]) {
l++;
r--;
} else {
if(!reverse(str.substring(l, r)) && !reverse(str.substring(l + 1, r + 1))) {
return false;
}
}
}
return true;
}
面试结束复盘
当时没有测试用例,少测试了一种情况,当删除一个字母就是回文子串的情况,没有终止条件,这个代码死循环了,而且我既然想到用索引的方式判断是否为回文字符串,那么我就不应该再用反转再去判断,而的这个逻辑 isSymmetry 中就是,我也不应该再去重复写一个一样逻辑的函数。
const isSymmetry = (str, flag = false) => {
let l = 0;
let r = str.length - 1;
while (l <= r) {
if (str[l] === str[r]) {
l++;
r--;
} else {
if (flag) {
return false;
}
if (
!isSymmetry(str.substring(l, r), true) &&
!isSymmetry(str.substring(l + 1, r + 1), true)
) {
return false;
}
return true;
}
}
return true;
};
这是我说不知道最多的一场面试,被虐的很惨,发现自己很多不足,接下来就是要弥补这些不足,去精读浏览器工作原理于实践这个专栏,按照之前的效率,应该是凉了...
6 月 22 日
0.1 + 0.2 !== 0.3 为什么
IEEE 754 了解吗
什么什么的几种(计算机组成原理相关的)算法?
TCP 拥塞控制?
TypeScript 高级用法, Pick 和 Omit
泛型的理解
webpack 和一面差不多吧
React Fibler
实现一个自定义 hook, 刚开始案例是 useState,我没问明白一直以为实现一个 useState,后来才发现是实现自定义 hook...
讲讲常用的 hook 打出来
用正则表达式获取 url 中 query 参数
let str = "https://juejin.cn?name=zhangsan&age=18&id=123";
function getUrlParams = ()=> {
let obj = {};
for (let i = 0; i < splitStr.length; i++) {
let temp = splitStr[i].split("=");
obj[temp[0]] = temp[1];
}
return obj;
}
console.log(obj);
你总结一下这场面试
n 叉树层序遍历
const levelOrder = (root) => {
while (root.length) {
const temp = root.shift();
console.log(temp.val);
for (let i = 0; i < temp.children.length; i++) {
root.push(temp.children[i]);
}
}
};
const root = [
{
val: 1,
children: [
{
val: 3,
children: [],
},
],
},
{
val: 2,
children: [
{
val: 4,
children: [],
},
],
},
];
1 个小时 10 分左右
计算机基础很重要,后期一定要系统学一下,正则表达式用的太少了,参加比赛用的都是 C 语言,所以一直不爱背 API 现在吃大亏了,一面剪切字符串刚开始就是自己封装的,现在又不长记性,唉,当时心都凉了,晚上 hr 说通过了,周五三面...
6月25日
const twoSum = (arr, target) => {
const obj = {};
for(let i = 0; i < arr.length; i++) {
if (obj[arr[i]] != null) {
return [obj[arr[i]], i];
} else {
obj[target - arr[i]] = i;
}
}
return [];
};
const twoSum = (arr, target) => {
const res = [];
for(let i = 0; i < arr.length - 1; i++) {
for(let j = i + 1; j < arr.length; j++) {
if(arr[i] + arr[j] === target) {
res.push([i, j]);
}
}
}
return res;
}
twoSum([2,7,11, 7], 9);
// 打印个这个 0, 1, 0, 3
牛客把我的数组给展开了, 我当时就有点懵, 这是啥, 有检查一遍代码, 没问题啊, 您好我可以打开控制台调试一下吗
image.png
再上一个问题开始的时候, 我就一直再想怎么优化, 毕竟面试了好几次了, O(n^2)一定会让我去优化的
const twoSum = (arr, target) => {
let obj = {};
let res = [];
for(let i = 0; i < arr.length; i++) {
if(obj[arr[i]] != null) {
let temp = obj[arr[i]];
for(let j = 0; j < temp.length; j++) {
res.push([temp[j], i]); // res.push([temp[j], i); 当时这里少打一个 ]
}
} else {
let temp = target - arr[i];
obj[temp] = obj[temp] ? [...obj[temp], i] : [i];
}
}
return res;
}
image.png
牛客这个报错信息, 不知道是面试官给的条件不一样还是怎么回事, 每次报错信息都不太一样, 最开始视频架构部门面试打错了, 提示的挺详细啊, 又看一遍代码逻辑没错啊, 然后我就申请打开控制台了
image.png
然后开始解释思路, 抬头看下时间已经 25 分钟, 写的有点久了啊
48 分钟
接着复盘
// 我当时觉得最差的情况是这个
twoSum([2, 2, 2, 7], 9);
// n + n - 1
// 但一半一半才最差,
twoSum([2, 2, 7, 7], 9);
// (n / 2) + (n/2) * (n/2)
// 而且我还忽略了一种情况, 这个 else 不应该加
twoSum([2, 7, 2, 7], 9);
const twoSum = (arr, target) => {
let obj = {};
let res = [];
for(let i = 0; i < arr.length; i++) {
if(obj[arr[i]] != null) {
let temp = obj[arr[i]];
for(let j = 0; j < temp.length; j++) {
res.push([temp[j], i]);
}
}
let temp = target - arr[i];
// obj[temp] = obj[temp] ? [...obj[temp], i] : [i];
// 用 push 更好一点
obj[temp] ? obj[temp].push(i) : obj[temp] = [i];
}
return res;
}
这场面试题写完之后, 后面也不那么紧张了, 但感觉题写的有点久了, 而且后面面试官也没问什么问题, 好像我也没什么值得他问的了,感觉到面试官对我不感兴趣了,后面聊天打了个哈欠,我可能耽误人家午休了吧(下午两点),之后又贴近了镜头整了整头发,缺少亮点啊。
6月28日,三天了,没消息,问下 hr, 果然没通过。
关注公众号秋风的笔记
,一个专注于前端面试、工程化、开源的前端公众号
简历
获取100+套的精美简历模板好友
拉你进技术交流群+面试交流群秋风的笔记
喜欢这篇文章?点个“在看”吧~▼