转眼间,入行已经1年4个月了,从最初的面试者,成长为现在的面试官,真切地意识到自己当初第一次面试表现很糟糕啊。
所以,我把当初第一次面试的2道算法题拿了出来,重新做一遍。诶,做完其实觉得挺简单的。
第一道题:
给定一组顺序数组和一个数字,若数组中存在该数字,则返回该索引值, 如果不存在,则按顺序插入数组,并返回数组和插入的索引值。
你需要原地修改该数组,不能产生新数组。
比如
[1,2,4,5] 6 // 返回[1,2,4,5,6] 索引值 4
[1,3,5,7] 3 // 返回 索引值 1
[2,7,8,9,10] 8 // 返回 索引值 2
[2,7,8,9,10] 6 // 返回[2,6,7,8,9,10] 索引值 1
这道题其实就是给出了业务需求,让你实现它,考验数组操作的基本功,是一道比较好的面试初级工程师的题目。
/**
* @param {number[]} nums
* @param number
* @return {number[]} index
*/
function sortPush(nums, item) {
let isHave = nums.findIndex(e => e === item)
if (isHave > -1) {
return isHave
}
for (let i = 0; i < nums.length; i++) {
if (item < nums[i]) {
nums.splice(i, 0, item)
return i
}
}
nums.push(item)
return nums.length + 1
}
很简单,第一步,利用 findIndex 查找一遍,如果存在,则直接返回其 index;
第二步,按大小比较,如果 a 比 b 大,则一直往后推,直到遇到比 a 大的数,然后利用 splice 插入进去;
但是,在第二步中可能存在一个情况,就是 a 比数组中的任何一个数都大,它会被一直推到最后边,导致不能执行插入操作,所以便有了第三步,直接在后边推入数字 a 。
当然,把第一步合并到第二步的循环中,一起判断,也是可以的。
这道题即考察了数组操作,也考察了边缘情况的考虑。毕竟当初是直接在A4纸上答题,如果不用机器跑一遍,是很可能遗忘掉第三步的考虑的。
第二道题:
给定两组长度不同的数组,比较两组数组的排列格式是否相同,相同则返回true,不同则返回false。 比如
["a",1,"a",1] , ["b",2,"b",2]
// 两组数组的排列格式都为abab形式,返回true
["c","c","c","e"] , ["f","f","2","g"]
// 第一组的格式为aaab,第二组的格式为aabc,返回false
["j","1","j","2","c","c","a"] , ["b","3","b","4","l","l","i","a"]
// 第一组长度及格式与第二组不同,返回false
光看题目,我当时也以为是考数组对比,还在傻傻地来回判断数组A是什么格式,数组B又是什么格式,但其实,考的是对数据结构的应用。
function isSameFormat(ary1, ary2) {
if(ary1.length !== ary2.length) {
return false
}
let mapping = {}
for (let i = 0; i < ary1.length; i++) {
if(ary1[i] in mapping) {
if(ary2[i] !== mapping[ary1[i]]) {
return false
}
} else {
mapping[ary1[i]] = ary2[i]
}
}
return true
}
第一步很简单,判断两条数组的长度是否一致,如果不一致,直接返回false。
第二步,我们思考一下,AB两条数组的格式相同,是不是就说明,AB数组中的元素其实是一一对应的。如果数组A中的第一个 c ,对应着数组B中的 j,那么数组A中的下一个 c ,在数组B中也应该对应着一个 j 。
这恰恰是 对象映射,所以,我们可以创建一个空对象,来记录这种映射关系,也即是代码中的mapping。
如果映射关系存在不同,则直接返回false。如果全部相同,则在最后返回true。
最后
这两道题,当初都是直接在A4纸上写的,两道都没答出来,第一道题“基础不牢,地动山摇”,第二道题不懂得运用对象数据结构。
现在回头看这两道题,挺简单的,但对于当时刚入行的我来说,感觉是挺好的验金石啊。