面试:百度一面,吓尿了

前言

在百度的学长,帮我内推了下简历。高兴还没有两秒,就接到通知面试的电话,瞬间压力山大。小公司也没怎么面,八股文背的也不利索,看到镜头里又秃又强的面试官的那一记得,有如看恐怖片吓尿了。

百度一面

1. 宇宙铁律,介绍下自己

还好,之前看到过敖丙大佬面试自我介绍5句话公式 - 掘金 (juejin.cn)一文,里面有个公式:我是谁+从哪里来+我做过什么+有什么成绩+为什么能胜任。

面试官您好,我叫梦梦,东华理工大学25届软件专业大三在读,想来百度前端岗位实习,要是是AIGC项目就更好了。低年级的时候,跟着学长一起在B站学习、打些比赛,拿过蓝桥杯省二,奖学金也拿了一些。个人比较喜欢前端,也能用node写后端。chatgpt火了后,又对AIGC非常感兴趣,所以学习了python、prompt enginneering、吴恩达AI课程等,平时写代码会用一些AI Copilot工具提升编程效率。

仔细读过《你不知道的JavaScript》,并在掘金上写过JS基础和底层相关系列文章,热爱技术分享,掘金优秀作者。平时主要使用vue,熟悉全家桶开发,数据流按理及后台管理系统开发。阅读过vue、axios、ElementPlus的源码,未来会持续学习。

未来最大的机会是AI的机会, 非常期待在AIGC产品或项目写下自己的代码。同时非常看好百度代表中国队参与AI技术革命,为用户开发划时代的产品与体验。未来几年,我将为此而奋斗, 谢谢。

2. promise有几种状态,可以重复改变吗?

Promise对象有三种状态

Pending(未决)初始状态

Fulfilled(已履行/成功):操作成功完成时的状态

Rejected(已拒绝/失败):操作因错误或异常未能完成时的状态

Promise状态变化的特性是:

Promise状态的转变是不可逆且只能发生一次。也就是说,一个Promise不能从Fulfilled状态变回Pending状态,也不能从Rejected状态变为Pending或者Fulfilled状态。 一旦Promise从Pending状态变为Fulfilled(resolved)或Rejected(rejected),它就永远不会再改变。

因此,Promise的状态不能重复改变。

感觉回答的还可以,记得去字节的会长提醒面试时,切忌一个字一个字的蹦面试官。面试不只是回答问题,而是要展示自己。抓住熟悉的知识或技能点,就来个滔滔不绝,面试官不喊停就一直说。于是想到下面这个API:

Promise.resolve()与Promise.reject() 用于创建已确定状态的Promise对象,方便快速返回成功的或失败的结果

面试官一听这个就感兴趣了, 继续提问Promise还提供了哪些静态方法,平时怎么用的?开心, 面试官进包围圈了。

  • Promise.all(iterable)

参数是promise对象数组。只有当所有Promise都变为fulfilled时,返回的Promise才会变为fulfilled,并且结果是一个包含所有Promise结果的数组;只要有一个Promise变为rejected,则整体Promise也会立即变为rejected,返回第一个rejected Promise的理由。

  • Promise.race(iterable)

在传入的 Promise 数组中任何一个 Promise 解决(resolve)或拒绝(reject)时,会立即以那个率先改变状态的 Promise 的结果为准来解决或拒绝。

这里强调下细节,其它的promise实例仍然会继续运行,只不过其状态和结果不会归于最终的结果。

Promise.race 关注的是速度最快的 Promise 的结果,而 Promise.all 关注的是所有 Promise 是否都成功完成。

  • Promise.allSettled(iterable)

Promise.all()相似,它等待所有Promise都达到settled状态(即无论是fulfilled还是rejected)。一旦所有Promise都决断了,返回的Promise会变成fulfilled,并且结果是一个数组,包含了每个输入Promise的结果描述对象,这些对象具有status('fulfilled'或'rejected')和对应的valuereason属性。

Promise.all() 更关注所有 Promise 是否都成功完成,它适用于需要所有任务成功完成才能继续下一步场景。而 Promise.allSettled() 则允许你观察一组异步操作的所有结果,无论成功与否,这对于获取并处理所有任务的最终状态非常有用。

到此,在三种状态的语法回答外,还将并发任务及sellted等偏业余的需求表演给面试官,看表情他还是挺满意的... 如果面试官不打断,我准备继续聊异步、红绿灯、手写promise... 面试就要变被动为主动,将自己擅长的表演出来。

3. 输出结果,为什么?

js 复制代码
const obj3 = {a: 1}; 
const obj4 = {b: 2}; 
console.log(obj3 == obj4); // false 
console.log(obj3 === obj4); // false

结果:

js 复制代码
false,false

原因:

  • == 值相等, ===严格相等,即值和类型都相等
  • 类型转化,虽然obj3obj4 值不一样,但面试官要听的是我们对于JS类型转换的理解。
javascript 复制代码
在转换不同的数据类型时,相等和不相等操作符遵循下列基本规则:

如果由一个操作数是布尔值,则在比较相等性之前先将其转换为数值---false转换为0,而true转换为1;
如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值;
如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较;
这两个操作符在进行比较时则要遵循下列规则。

null和undefined是相等的。
要比较相等性之前,不能将null和undefined转换成其他任何值。
如果有一个操作数是NaN,则相等操作符返回false,而不相等操作符则返回true。重要提示:即使两个操作数都是NaN,相等操作符也返回false;因为按照规则,NaN不等于NaN。
如果两个操作数都是对象,则比较他们是不是同一个对象。如果两个操作数都是指向同一个对象,则相等放回true,否则返回false。

所以这里不会转换两个对象,而是比较他们是不是指向同一个地址,是否是同一个对象。

  • ===严格相等,这里比较的也是引用地址。

所以,在比较两个对象时,并不会发生类型转换以试图使它们相等。相等性判断直接基于对象的内存地址。

4. leetcode 原题编辑距离

js 复制代码
给你两个单词 `word1` 和 `word2`, 请返回将 `word1` 转换成 `word2` 所使用的最少操作数。

你可以对一个单词进行如下三种操作:

-   插入一个字符
-   删除一个字符
-   替换一个字符

首先,这道动态规划题有些复杂,大家需要刷一些基础的动态规划题再来搞这道。像百度等这种级别的大厂,算法题我称为三板斧。一般是1-2道简单或中等题,再是1-2道有难度的动态规划题。只要我们准备好动态规划由简到难的各种常考题型,扛住面试官的前三板斧子,基本没有问题。

  • 举例
js 复制代码
word1  horse
word2  ros
1. word1 变
horse ->  rorse    h->r  替换
rorse -> rose      删除最2个r
rose-> ros         删除最后e 

操作次数是3次  由word1 变成word2

再换个思考 由word2变成word1也是可以的
2. word2 变
ros -> rose   添加e
rose->rorse  添加r 
rorse-> horse r 替换为h
其实就是上面的逆向操作

3. 都变
horse ->  rorse    h-> r  word1 变
rorse -> rose    删除r    word1 变
ros -> rose      word加e      word2 变

word1 和word2 都操作了, 一共操作了3次
分析demo,方便等下我们考虑最优子结构的各种情况

天啊, 太复杂了,替换、删除、添加三种操作、两个单词混合修改。别怕,最值问题求解,就用动态规划。看上去复杂的dp问题,使用动规五部曲就能化腐朽为神奇。

动规五部曲

  • 定义dp数组 比较两个字符串,那么我们要定义一个二维的dp[i][j],两个字符串的最少操作次数(无论哪个操作字符,哪种操作,都可以用二维矩阵涵盖)

    以i-1结尾的word1 ,以j-1结尾的word2

    dp[i][j]就是让两个字符相同的最少操作次数,根据动态规划的局部最优亦是全局最优,最后的dp[m][n]就是我们要的结果

  • 递推公式

我们要比较两个字符串,就要比较每个元素,那么要比较哪些元素呢?

word1[i-1]、word2[j-1] 递推,自顶向下思考

js 复制代码
// 如果两个字符相同
if (word1[i-1] == word2[j-1]) {
    // 不需要添加、删除、替换元素
    // 最少操作次数可以是不改变的,取上一次的最少操作数,因为dp局部最优也是全局最优的
    dp[i][j] = dp[i-1][j-1]
} else {
// 上操作
    // dp[i][j] = dp[i - 1][j - 1] + 1, // 替换操作
    // dp[i][j] = dp[i][j - 1] + 1, // 插入操作
    //dp[i - 1][j] + 1)// 删除操作
    dp[i][j] = Math.min(
          dp[i - 1][j - 1] + 1, // 替换操作
          Math.min(dp[i][j - 1] + 1, // 插入操作
                   dp[i - 1][j] + 1) // 删除操作
        );
   // 总之, 根据动态规划的思想,只要有一步操作就可以到达
}
  • 初始化

怎么来考虑初始化问题呢? 上图dp[i][j]会由左上角的dp[i-1]j-1、左边dp[i-1][j]、上边dp[i][j-1]三个方向迭代而来。所以在初始化的时候,我们需要把第一行dp[]和第一列都初始化,这样就可以递推出相应的值。

js 复制代码
 for (let i = 0; i <= m; i++) {
    dp[i][0] = i;
  }
  for (let j = 0; j <= n; j++) {
    dp[0][j] = j;
  }
  • 迭代
js 复制代码
//自底向上, 迭代

for (let i = 1; i <= m; i++) {
    for (let j = 1; j <= n; j++) {
       .....
    }
}
  • 返回结果

最后的dp[m][n] 也就是二维矩阵的右下角。

通过动态规划五步走,代码如下:

js 复制代码
/**
 * @param {string} word1
 * @param {string} word2
 * @return {number}
 */
function minDistance(word1, word2) {
  const m = word1.length;
  const n = word2.length;

  // 初始化一个(m+1) x (n+1)的矩阵,第一行和第一列分别表示空串到word1前i个字符、空串到word2前j个字符的距离
  const dp = new Array(m + 1).fill(null).map(() => new Array(n + 1).fill(0));

  // 初始化边界条件:空字符串转换成任意长度的字符串至少需要该字符串的长度次操作
  for (let i = 0; i <= m; i++) {
    dp[i][0] = i;
  }
  for (let j = 0; j <= n; j++) {
    dp[0][j] = j;
  }

  // 动态规划填充矩阵
  for (let i = 1; i <= m; i++) {
    for (let j = 1; j <= n; j++) {
      if (word1[i - 1] === word2[j - 1]) {
        dp[i][j] = dp[i - 1][j - 1]; // 如果两个字符相等,则不需要消耗操作次数
      } else {
        dp[i][j] = Math.min(
          dp[i - 1][j - 1] + 1, // 替换操作
          Math.min(dp[i][j - 1] + 1, // 插入操作
                   dp[i - 1][j] + 1) // 删除操作
        );
      }
    }
  }

  return dp[m][n]; // 最终答案位于dp数组右下角
}

5. 如何用AI工具 提升开发效率

  • 之前申请了Github的Copilot,学生党免费嘛。对代码提速和源码学习都有挺大帮助的。也试过下通义千问的vscode 插件,挺好的。
  • 使用各种chat bot(Chatgpt等),从前端到后端、AI学习、数据库等,提问式学习及解决问题,拥抱AI Native。
  • 刻意练习一些prompt 的技巧, 生成前端页面、SQL等 比如在做后台管理系统的时候, tailwind的一些页面,基本都是chat 完成。
  • 学习transfromer、openai 等AIGC类技能,将一部分的编程任务交给Agent来完成,发挥大模型的能力。最近在学习LangChain, 对AI很感兴趣。

总结

百度的面试还是比较专业的,能学到很多东西。对于刚准备春招的我,真是有点吓尿了。不管结果怎么样, 继续前行吧,要去亲戚家拜年了, 先写到这,下一篇继续聊....

参考资料

假如您也和我一样,在准备春招。欢迎加我微信shunwuyu,这里有几十位一心去大厂的友友可以相互鼓励,分享信息,模拟面试,共读源码,齐刷算法,手撕面经。来吧,友友们!

相关推荐
y先森4 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy4 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189114 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿5 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡6 小时前
commitlint校验git提交信息
前端
虾球xz6 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇6 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒6 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员7 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐7 小时前
前端图像处理(一)
前端