工友们,看到题目,先别愤怒,第一小节,咱们先铺垫讲一个 “面试问题应该从问【是什么】到问【为什么】” 的逻辑。
🤔面试问题从【是什么】到【为什么】
关于前端是否有必要面试算法,本瓜看过很多争论,相信你也一样听过不少,诸如此类:
正方:
“工作中又用不到,有必要吗?”、“一般后端都会把数据格式处理好”、“算法跟面试背八股文一样,不能测出真实能力”。。。
反方:
“面试内卷,拉开层次,算法必会”、“数据结构和算法是程序员的基本功”、“处理复杂场景,算法思维能提供更大帮助”。。。
这里不去谈论两类阵营的观点孰对与错,而想分享一位大佬的经验,从另外一个角度看待这个问题:
原话:
面试应该搞清楚【为什么】,而不是停留在【是什么】。
什么意思?
如果面试官问你某一个问题,你没答出来,他就以此判定你“不合格”,那这位面试官也是“不合格”的。判定应试者不知道某一个问题,属于【是什么】(是不是知道?);合格的面试官、应该深挖一步,追问【为什么】(为什么不知道?)。是因为平常没有遇到过这样的类似场景吗?还是因为采用的是其它技术手段或方案?或者因为更擅长别的点?。。。如果现在遇到了,会怎么去考虑呢。。。
每个人的经历、经验不一样,结合分析问应试者【为什么】,顺着一个思路问下去,进行更深入、有效的交流,能更好的去匹配职位需求。
那么,再看“前端是否该面试算法”问题,用这个逻辑来想想。
-
不知道数据结构堆、栈、BFS、DFS 这些。 —— 为什么不知道?因为非科班出身,半路转岗?因为平常都在专注业务开发,对业务理解更透彻,数据结构这些都忘了?
-
递归算法写不出来 —— 为什么写不出?因为平常写的少、对递归不熟悉?还是因为对面试题的理解、过程抽象有问题?
-
LRU、LFU 缓存算法没听过 —— 为什么没听过?vue keep-alive 缓存组件的策略了解过吗?是因为平常对 http 缓存或 dns 缓存关注更多吗?
......
一场好的面试一定是应试者和面试官双方都在吸收、成长。
(小技巧:下一次,如果遇到面试官直白的问:你会写 XX 算法吗?而刚好你听都没听过,不用紧张,你可以沉着、冷静、平和的反问:我之前工作中没接触过这个算法,单纯好奇啊哈哈,我想问下您这个算法在前端都有哪些应用场景?)
🤬“工作两年,这么简单的算法题都不会?”
好了,有了第一小节的铺垫,我们再来看本文标题。(这句话来自于 fatfish 的一位朋友最近经历的一场面试中面试官说的。传送门:medium)
听完后,作为应试者,几乎可以愤怒回怼这个面试官:我不会怎么了呢?工作不照样好好的?两年怎么了?吃你家一粒米了吗?你了解我的经历吗?我出套八股文面试题,你敢来面吗?想不通,去一边自己慢慢想去吧~~
......
理性一点思考:这位面试官不懂问【是什么】到问【为什么】的面试逻辑,估计他准备的题目也是挺随意的吧,或者一直局限于自己的一点眼界。
也属实没必要跟这号人打嘴仗了,纠缠不休,嘴贱自有天收。(这么没礼貌的面试官即使存在,应该也是少数)不如咱心态好一点,坚持自己的逻辑:从面试经历中吸收、成长就好。
技术题目无罪,不要让不好的面试体验干涉到技术学习上来。
有些算法题,想想也挺有意思~ 用平静的心态一起来看看这位两年经验老哥遇到的什么题?上题!
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
例1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
例2:
输入: nums = [3,2,4], target = 6
输出: [1,2]
例3:
输入: nums = [3,3], target = 6
输出: [0,1]
噢!刷过力扣的 xdm 应该都知道了,此题典中典,题库第一题 (就像英语四级的 abandon) —— 两数之和。
江湖上还流传过【不知两数和,刷尽力扣也枉然】的言论;看评论,这题甚至还难倒过某博士生老哥🐶 哈哈哈,其特殊可见一斑!
刷过此题的都知道:这题考察的不是双层 for 循环暴力解题,而是转换思路,用 map,减少使用一层 for 循环,降低时间复杂度解题;
所以面试官看似问你怎么解题,实则留了一手,要问你:怎么优化暴力解法?
如果之前又恰好没有看过、学习过这类转换思路,在面试的情况下,短时间有可能真的就想不起来。
解一:双层 for 循环暴力解法
const twoSum = (nums, target) => {
const len = nums.length
for (let i = 0; i < len; i++) {
// 因为同一元素不允许重复出现,所以从i的下一位开始遍历
for (let j = i + 1; j < len ; j++) {
// find the answer, return
if (nums[ i] + nums[ j ] === target) {
return [ i, j ]
}
}
}
}
解二:利用 map 解,降低时间复杂度
var twoSum = function(nums, target) {
const map = new Map();
for(let i = 0, len = nums.length;i < len;i++) {
// 一层遍历,用 target 减去每一项,在 map 的 key 中寻找
if(map.has(target - nums[i])) {
// 存在则返回结果
return [map.get(target - nums[i]), i];
}
// 不存在,则设置 map key 和 val
map.set(nums[i], i);
}
return [];
};
这位两年经验老哥就是这样,回答出来了第一种解法,在第二种解法折戟。
无奈,面试官总想要的更多......
其实也不止这题,很多面试算法题都是这样,暴力解法只是整个问题的第 1 小问,关键是第 2 小问怎么转换思路、优化暴力解法,减少时间/空间复杂度。
无独有偶,这让我想起:当本瓜还是前端二年级生的时候,就在某次大厂面试中遇到过和这个非常类似的算法面试题,以前的文章提到过-剑指 Offer II 016. 不含重复字符的最长子字符串,后来我才知道这题优化双层 for 循环暴力解法思路 —— 滑动窗口,当时是真的一点不知道。
好在,那位面试官没有说:“这都不会?” 不然直接自闭。
小结一两句:
愿技术大牛、老大哥们,对新人多一点善意吧。不是谁都是高校计算机科班出身、有大厂实习经验、或遇到贵人指出职业规划、学习重点等等。
我就见过也还不少吧,学材料的、学金融的、甚至学雕塑的,转投互联网行业,学技术、做开发。没有计算机基础,没看过数据结构的书。有家庭需要去支撑、有在大城市打拼站住脚的想法;没有孰好孰坏,大家经历不一样、阶段不一样而已。
前端面算法,可以,说出个条条道道,通过一场面试,能帮助应试者能成长,也是帮自己成长吧。找工作而已,说难听的话,没必要。
OK,以上便是本篇分享。点赞关注评论,为好文助力👍
我是掘金安东尼 🤠 100 万人气前端技术博主 💥 INFP 写作人格坚持 1000 日更文 ✍ 关注我,安东尼陪你一起度过漫长编程岁月 🌏
我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿。