面试:百度一面,吓尿了

前言

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

百度一面

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,这里有几十位一心去大厂的友友可以相互鼓励,分享信息,模拟面试,共读源码,齐刷算法,手撕面经。来吧,友友们!

相关推荐
贵州晓智信息科技3 分钟前
如何优化求职简历从模板选择到面试准备
面试·职场和发展
brrdg_sefg11 分钟前
Rust 在前端基建中的使用
前端·rust·状态模式
m0_7482309436 分钟前
Rust赋能前端: 纯血前端将 Table 导出 Excel
前端·rust·excel
qq_5895681044 分钟前
Echarts的高级使用,动画,交互api
前端·javascript·echarts
黑客老陈2 小时前
新手小白如何挖掘cnvd通用漏洞之存储xss漏洞(利用xss钓鱼)
运维·服务器·前端·网络·安全·web3·xss
正小安2 小时前
Vite系列课程 | 11. Vite 配置文件中 CSS 配置(Modules 模块化篇)
前端·vite
暴富的Tdy2 小时前
【CryptoJS库AES加密】
前端·javascript·vue.js
neeef_se2 小时前
Vue中使用a标签下载静态资源文件(比如excel、pdf等),纯前端操作
前端·vue.js·excel
m0_748235612 小时前
web 渗透学习指南——初学者防入狱篇
前端