前端面试的一些算法

622 阅读4分钟

**** 只是为了给我自己看的,别事多 ****

冒泡排序

function mySort(ary){
    if(ary.length <= 1) return ary; // 就一个时无需排序
        // 从第一个开始,最后一个就不用比较了
	for(let i = 0 ; i < ary.length - 1 ; i++){
	       // 从第一次循环的后一个开始
		for(let j = i + 1 ; j < ary.length ; j++){
		        // 对比第一个和它的后一个
			if(ary[i] > ary[j]){
			    // 如果第一个比它的后一个要大,那就需要让它俩换一个位置
				let temp = null;
				temp = ary[i];
				ary[i] = ary[j];
				ary[j] = temp;
			}
		}
	}
	return ary;
}
let ary = mySort([4,3,2,1]);
console.log(ary);// [1, 2, 3, 4]

快速排序(马蜂窝面试题)

function quickSort(arr) {
    if(arr.length <= 1) return arr; // 一个元素时就无需排序了
    let leftArr = []; // 定义一个数组,用来放比基数小的数
    let rightArr = []; // 定义一个数组,用来放比基数大的数
    let mid = arr[0]; // 默认选取数组的第一个为基数
    for(let i = 1; i<arr.length; i++) {
        // 因为已经取了第一个为基数,所以此处从第二个开始循环。
        if(arr[i] > mid) {
            // 如果当前值大于了基数,就将它扔进大的数组中
            rightArr.push(arr[i]);
        }else{
            // 如果当前值小于或等于了基数,就将它扔进小的数组中
            leftArr.push(arr[i]);
        }
    }
    // 将左边数组和基数和右边数组,组成一个新的数组扔出去
    // 此处之所以去递归调用此函数,是因为它需要一次又一次的正确排列顺序
    return [...quickSort(leftArr), mid ,...quickSort(rightArr)]
}
let a = quickSort([3,2,1,1,2,3]);
console.log(a); // [ 1, 1, 2, 2, 3, 3 ]

以数组中每一项的最后一位来排序(猫眼电影面试题)

    var ary = [35, 23, 17, 31];
    function fn(ary){
        for(let i=0;i<ary.length-1;i++){
            for(let k = i+1;k<ary.length;k++){
                // %10 取余数
                if(ary[i] % 10 > ary[k] % 10){
                    let temp = null;
                    temp = ary[i];
                    ary[i] = ary[k];
                    ary[k] = temp;
                }
            }
        }
        return ary;
    } 
    var a = fn(ary);
    console.log(a); // [ 31, 23, 35, 17 ]

不通过临时变量进行两个整数的交换

    var a = 5;
    var b = 8;
    b = b - a; // 3
    a = a + b; // 8
    b = a - b; // 5

兔子数列(马蜂窝面试题)

function rabbit(max) {
    //max要是大于等于2的整数
    var a = 0 , b = 1 , arr = [0,1];
    // 之所以要定义a和b,是因为兔子数列是从第三个元素开始,它是前两个元素的和,定义a和b用来等于前两个数,初始值为0和1是因为所有数列的初始值都是从0和1开始的
    // 定义arr为长度为0和1的数组,是因为最后的相加元素都是从0和1开始的,所以这里就先订了,之后就直接从它length的下个开始走就行了
    while (arr.length < max) {
        // 第二个值为前两项相加的结果
        [a,b] = [b,a+b]; //es6的解构
        // 将每次相加后的结果扔进数组中
        arr.push(b);
    }
    return arr;
}

let r = rabbit(10);
console.log(r); //[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

获取url参数(嘀嘀出行-平台效能部-内部平台面试题)

    function queryPath(url){
        let res = /([^?&=]+)=([^?&=]+)/g;
        let obj = {};
        url.replace(res,function(){
            obj[arguments[1]] = arguments[2];
        });
        return obj;
    }
    let queryObj = queryPath('https://www.baidu.com?name=gn&age=18&address=北京');
    console.log(queryObj);// {name: "gn", age: "18", address: "北京"}

获取字符串中出现次数最多的字符

    function fn(str){
        if(str.length <= 1) return str;
        let obj = {};
        let maxKey = [];
        let maxValue = 1;
        for(let i=0;i<str.length;i++){
            let item = str[i];
            if(!obj[item]){
                obj[item] = 1;
            }else{
                obj[item]++;
            }
        }
        for(let key in obj){
            if(obj[key] >= maxValue){
                maxKey.push(key);
                maxValue = obj[key];
            }
        }
        return {maxKey,maxValue};
    }
    var s = fn('luojialu');
    console.log('出现最多的字符是:' + s.maxKey);
    // 出现最多的字符是:l,u
    console.log('出现最多的次数是:' + s.maxValue);
    // 出现最多的次数是:2

随机整数

    let str = 'abcdefghrgklmnopqrstuvwxyzABCDEFGHRGKLMNOPQRSTUVWXYZ0123456789';
    function codeRandom(str,count){
        let newStr = '';
        while(newStr.length < count){
            // 随机索引
            let strRandom = Math.floor(Math.random() * str.length);
            if(newStr.indexOf(str[strRandom]) == -1){
                // 确保不重复
                newStr += str[strRandom];
            }
        }
        return newStr;
    }
    let random = codeRandom(str,4);
    console.log(random)

将多维数组拍平

    function flat(ary){
        let newAry = [];
        for(let i=0;i<ary.length;i++){
            let item = ary[i];
            Array.isArray(item) ? 
            newAry.push(...flat(item)) : 
            newAry.push(item);
        }
        return newAry;
    }
    var arr=[1,2,[3,4,[5,6,7]],9,[10,11]];
    flat(arr); // [1, 2, 3, 4, 5, 6, 7, 9, 10, 11]

阶乘(柯里化思想)

    function f(...args){
        return args.reduce((prev,next)=>{
            // 当前的乘下一个的
            return prev * next;
        })
    }
    const curry = fn => {
        // 在不销毁的作用域处定义一个数组,用来保存每次传进来的值
        let _args = [];
        const _fn = (...args) => {
            // 将每次传进来的值扔进不销毁的作用域中的数组中,用来保存
            _args.push(...args);
            if(args.length >= 1){
                // 如果有传参,那就递归继续push进数组
                return _fn;
            }else{
                // 没有传参,执行传进来的函数f,返回累乘结果
                let r = fn(..._args);
                // 此处清空这个数组是为了防止多次调用参数堆积问题
                _args = [];
                return r;
            } 
        }
        return _fn;
    }
    let m = curry(f);
    let a = m(3)(4)(5)(); // 60
    let rusult = m(3,4,5)(); // 60
    let b = m(3)(4,5)(); // 60