前一阵去今日头条面试,两轮面试官都让手撕算法,撕完了还要在电脑上能运行,这倒是提醒我了一点,不能因为前端对算法要求没有客户端高就忽视它,只要是一个软件开发人员,就一定要有良好的算法基础。话不多说,现在来撕吧,哈哈哈~
第一题
嵌套数组打平并且去重,类似于这样
[3,2,4,5,6,1,5,4,[9,5,3,2,[10,4,6]]]=>[3,2,4,5,6,1,9,10]
能想到的数组去重方法挺多的,常规的有这么几种:
1.构建一个新的数组存放结果,for循环中每次从原数组中取出一个元素,用这个元素循环与结果数组对比,若结果数组中没有该元素,则存到结果数组中。
2.先将原数组进行排序,检查原数组中的第i个元素与结果数组中的最后一个元素是否相同,因为已经排序,所以重复元素会在相邻位置,如果不相同,则将该元素存入结果数组中。
3.创建一个新的数组存放结果,创建一个空对象,for循环时,每次取出一个元素与对象进行对比,如果这个元素不重复,则把它存放到结果数组中,同时把这个元素的内容作为对象的一个属性,并赋值为-1,存入到建立的对象中。
这里使用的是最后一个方法。对于嵌套数组的话,可以判定元素类型是否是数组类型然后利用递归解决。代码如下:
var arr = [3,2,4,5,6,1,5,4,[9,5,3,2,[10,4,6]]];
var newArr = [];
var obj = {};
function setInobj (arrx,n) {
for(var i=0;i<n;i++){
if(arrx[i] instanceof Array){
setInobj(arrx[i],arrx[i].length);
}
else{
if(!obj[arrx[i]]){
newArr.push(arrx[i]);
obj[arrx[i]] = -1;
}
}
}
}
setInobj(arr,arr.length);
console.log(newArr);
第二题
类似于这种形式
{
a : {
b : 1,
d : {
e : 2
}
},
f : 3,
g : {
h : 4
}
}
最 后 输 出:
{
'a/b' : 1,
'a/d/e' : 2,
'f' : 3,
'g/h' : 4
}
这个题刚开始觉得挺简单的,跟上面思路一样啊,利用递归,但是后来发现它要处理类似索引的那个东西,很傻的研究了半天,结果突然灵机一动就给写出来了,代码如下:
var preObj = {
a : {
b : 1,
d : {
e : 2
}
},
f : 3,
g : {
h : 4
}
};
var newObj = {};
function setInobj (obj,name) {
for(var i in obj){
if(typeof obj[i] == 'number'){
if(name !== ''){
newObj[name + '/' + i ] = obj[i];
}
else{
newObj[i] = obj[i];
}
}
else{
if(name !== ''){
setInobj(obj[i],name + '/' + i);
}
else{
setInobj(obj[i],i);
}
}
}
}
setInobj(preObj,'');
console.log(newObj);//{ 'a/b': 1, 'a/d/e': 2, f: 3, 'g/h': 4 }
其中name表示前面的索引值
第三题
两个有序数组进行合并,排序,不能使用concat,sort方法。
当时写的时候忽视了有序数组这个条件,直接利用push进行连接两个数组,然后利用优化冒泡来解决的。后来面试官引导我看有没有什么别的办法,我才注意到有序数组的条件,然后我就说了想法,他也没让我再实现(哈哈哈哈~~),不过每次面完都得总结一下,代码如下:
var arr1 = [1,5,6,9],arr2 = [3,5,7];
var temp;
for(var i = 0;i < arr1.length-1;i++){
if(arr2[0] >= arr1[i] && arr2[0] <= arr1[i + 1]){
temp = arr1[i];
arr1.splice(i,1,temp,arr2[0]);
arr2.shift();
}
}
console.log(arr1);
事实证明要记住数组常用的方法是很有用的,要不得实现好长一串代码。
等电话的过程好难熬啊啊啊啊啊,加油加油吧!