为了账号安全,请及时绑定邮箱和手机立即绑定

几道js面试题,一起来做做吧。

标签:
JavaScript

   趁着闲暇之时整理一些题目出来,一起看看吧。

  1、计算字符串中出现的所有目标字符的下标。比如输入:‘my name is dorsey’和’m’,输出:[0, 5]

  看到这道题,可能第一反应就是利用indexOf。如:

const getIndexOfString0 = (str, target) => {

    let res = [], i = str.indexOf(target);
    while( i > -1 ) {
        res.push(i);
        i = str.indexOf(target, i + target.length);
    }
    return res;
}
console.log( getIndexOfString0('my name is dorsey', 'm') );

  当然也可以通过最原始的方式,即遍历取值比对。


const getIndexOfString = (str, target) => {

    let res = [];
    
    for(let i = 0; i < str.length; i ++) {

        if(str[i] === target) {

            res.push(i);
        }
    }
    return res;
}
getIndexOfString('my name is dorsey', 'm');

  2、不使用排序,求一个乱序数组的最大和,比如输入 [1, 2, 3, 4, 5, 6, 7] 输出 7 + 6 = 13

  可能看到这个,首次的思路就是遍历数组取出最大的数,再移除最大的那个数,并将剩余的数组再一次的遍历取大者,就像下面这样:

const largestSum1 = arr => {

    let max = -Infinity, 
        secondMax = -Infinity;

    arr.forEach(item => max = max > item ? max : item);

    arr.splice(arr.indexOf(max), 1);

    arr.forEach(item => secondMax = secondMax > item ? secondMax : item);

    return `${max} + ${secondMax} = ${max + secondMax}`;
}

  但这个时候面试官可能还想考察的是你在做大小比对时的灵活运用,而这里刚好是可以利用Math对象的功能,就像下面这样。


const largestSum0 = arr => {

    let max = Math.max.apply(-Infinity, arr);

    arr.splice(arr.indexOf(max), 1);

    let secondMax = Math.max.apply(-Infinity, arr);

    return `${max} + ${secondMax} = ${max + secondMax}`;
}
console.log(largestSum0([1, 2, 3, 4, 5, 6, 7]));

  假如此时max函数是Array.prototype中的一个方法,是不是应用起来挺方便的?但实际上并没有,所以需要做一层映射,很巧的就在于apply的第二个参数刚好是一个数组,当然,将数组解构变成Math.max.call(-Infinity, …arr)也是可以的。在参数较少时,用call的性能会更好一些。

  3、对一个只会出现英文字母且不重复的字符串,求其缺失的字母,忽略大小写。比如字符串:‘abcdefghijkopqrstxyz’,就缺少了l、m、n跟u、v、w,输出此时的缺失字母。

  看到这个可能第一反应会事先构建一个完整从a~z的字符串数组,并遍历数组,查看是否存在于字符串中,这里我们虽然也是这样做,但却是通过一种更加巧妙的方式构建我们的字符串数组,并利用filter这个强大的过滤利器来完成我们的功能。

  其实,这里呢,字母或者是chat型的字符,无论是js也好,其他语言也好,都有一样的一个字典,也可能是枚举类,它们都遵循一样的unicode编码。而我们想要的这个从a-z的编码刚好是97 ~ 122,看看下图:
图片描述
  而这时我们就会想,既然有这样的对应关系,那我创建一个99到122的数组并通过这样的对应关系再映射回来,不就是一个完整的a~z了吗?看看:
图片描述
  那再将原本的数组遍历,换成filter的过滤,这样这道题对于我们来说就简单多了,也优雅多了。看看代码:

const getLostLetter = str => {

    let arr = Array.from({length: 26}, (item, index) => String.fromCharCode(index + 97));

    str = str.toLowerCase();

    return arr.filter(item => str.indexOf(item) === -1); 
}
getLostLetter('Abcdefgijklopqrstxyz');

  4、任务管理

假如现在有这样的一个情况:
  一个任务队列中,有任务优先级为高中低三种任务,按高中低的优先级在数组中排序。后续插入的任务也有高中低,需要将后续插入的任务放到对应的级别末尾,并且不能混乱到该任务队列。
  队列的结构可能是这样的:

let arr = [
    {
        rank: '高',
        taskID: '6b8ca06e'
    },
    {
        rank: '高',
        taskID: '7dac2d24'
    },
    {
        rank: '中',
        taskID: '668a451a'
    },
    {
        rank: '低',
        taskID: '6ad40d38'
    }
]

  假如此时再来一条任务,优先级为高,其实这时候要做的就是将这条任务插入到高优先级的最末尾。那怎么知道最末尾在哪,完整的数组在插入后是如何重新续上的呢?一起看看。

const taskManage = (arr, newTask) => {

    let rank = ['高', '中', '低'];

    let rankIndex = rank.indexOf(newTask.rank);
    
    let newArr = arr.filter(item => {
        for(let i = 0; i <= rankIndex; i ++) {
            if(item.rank === rank[i]) {
                return item.rank;
            }
        }
    });
    arr = [...newArr, newTask, ...arr.splice(newArr.length)];
    return arr;
}

return taskManage(arr, {
    rank: '高',
    taskID: '128a451a'
});

5、移动 0。一个数组里面有若干个 0,将这些 0 移至数组的开头,并保持其他值的相对位置不变。

  比如下面这样的数组:[1, 0, 2, 7, 0, 8, 0, ‘12’],最终需要输出:[0, 0, 0, 1, 2, 7, 8, ‘12’]。

  其中一个很简单也很暴力的做法就是,既然有0,和其他,那将数组做两次过滤,一次过滤出0来,一次过滤出其他的,由于filter并不会改变数组值的相对位置,刚好符合要求,比如下面这样:

const moveZero0 = arr => arr.filter(item => item === 0).concat(arr.filter(item => item !== 0));

console.log( moveZero0([1, 0, 2, 7, 0, 8, 0, '12']) );

  这第二种方式,其实就是规规矩矩的拿0放开头,像这样:

const moveZero = arr => {

    for(let i = 0; i < arr.length; i ++) {

        if(arr[i] === 0) {

            arr.unshift(...arr.splice(i, 1));
        }
    }
    return arr;
}
moveZero([1, 0, 2, 7, 0, 8, 0, '12']);

  每天跳出环境,学点新东西,一年后你会发现不一样的你。

点击查看更多内容
2人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
1.3万
获赞与收藏
1519

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消