面试题总结(三)之经典算法(建议收藏)

739 阅读6分钟

1、你会多少种数组去重方法?

2、你会多少种数组排序算法? 实现过程经常忘记?

3、数组扁平化的N种实现方案,你会几种?

4、阿里面试题之斐波那契数列,你的思路是?

5、加餐-今日头条算法题

数组去重

数组去重也是经典中的经典面试题,今天我们会用不同的思维去解决此问题。(👨‍🚒)

let arr=[12, 23, 12, 15, 25, 23, 25, 14, 16];

思路一:

你第一个想到的方案肯定是ES6new Set() 🤣

arr = [...new Set(arr)]arr = Array.from(new Set(arr))

毫无疑问,肯定是可以实现数组去重的目的!!!

如果不用ES6语法,你会怎么实现?

思路二:

声明一个新数组,依次取原有的数组中的元素,如果该元素不存在新数组中(比较的方法有很多 indexOf、includes、...,思路是相同的🤣),我们就将此元素添加至新数组中!

    let arr=[12, 23, 12, 15, 25, 23, 25, 14, 16];
    let newArr=[];
    arr.forEach((item)=>{
        if(newArr.indexOf(item)===-1){
            newArr.push(item);
        }
    });
    console.log(newArr);

思路三:

对原有的数组进行排序,相邻元素进行比较,不相同的元素放入新数组!

    let arr=[12, 23, 12, 15, 25, 23, 25, 14, 16];
    let newArr =[];
    arr = arr.sort((a,b)=>{
        return a-b;
    });
    newArr.push(arr[0]);
    for(let i=1;i<arr.length;i++){
        if(arr[i]!==arr[i-1]){
            newArr.push(arr[i]);
        }
    }
    console.log(newArr);

思路四

利用对象键值对的唯一性

    let arr=[12, 23, 12, 15, 25, 23, 25, 14, 16];
    let obj={};
    arr.forEach(item=>{
        obj[item] = item;
    });
    console.log(Object.keys(obj).map(Number));

大概就这些思路了吧,欢迎补充!!!🙃

数组排序

冒泡排序

let ary = [12,8,24,16,1];

思路:

1、相邻的元素相比较,左边的元素大于右边的元素则交换位置。

2、第一轮结束后,最大的数会排在数组的末尾 . . .

3、每轮结束后,数组中较大的数都会移动至尾部

分析:

第一轮结束后:

[8,12,16,1,24]

第二轮结束后:

[8,12,1,16,24]

第三轮结束后:

[8,1,12,16,24]

第四轮结束后:

[1,8,12,16,24]

经过4轮,我们获得了有序的数组:

因此长度为n的数组,我们需要进行n-1轮排序

代码实现:🙃

function ArraySort(){
    let arry = [12,8,24,16,1];
    //需要排序的轮数
    for(let i=1;i<arry.length;i++){
    //每轮需要比较的次数
        for(let j=0;j<arry.length-i;j++){
        //交换位置
            if(arry[j]>arry[j+1]){
                let temp = arry[j];
                arry[j]=arry[j+1];
                arry[j+1]=temp;
            }
        }
    }
    console.log(arry);
}

插入排序

想象一下,你现在正在斗地主😇,牌库 [12,8,24,16,1],每当你从牌库中抓取一张牌时,你需要与手中的牌进行大小比较,手上的牌按照升序进行排序,那么你每抓取一张牌都会放入合适的位置。

开始抓牌:😂

function insertArray(arry){
    //你的手牌
    let handleArr=[];
    //将第一张牌抓入手中
    if(arry.length>0){
        handleArr.push(arry[0]);
    }
    //依次抓取牌库中的牌
    for(let i=1;i<arry.length;i++){
        //手上的牌
        for(let j=handleArr.length-1;j>=0;j--){
            //从右边开始,依次与你手中的牌比较,大于则插入
            if(arry[i]>handleArr[j]){
                handleArr.splice(j+1,0,arry[i]);
                break;
            }
            //如果手牌都比抓取的牌大,则放在首位
            if(j===0){
                handleArr.unshift(arry[i]);
            }
        }


    }
    console.log(handleArr);
}

insertArray([12,8,24,16,1]);

快速排序

快排思路:

1、选取一个参考值,这个参考值会影响快排的效率,一般我们选取中间的数作为参考值

2、比参考值小的数放入一个数组中,比参考值大的数放入一个数组中

3、重复 1、2步骤,直至划分的数组长度为1

4、把步骤3划分的数组拼接起来就得到了一个有序的数组

function quickArray(arry){
    //数组长度为1时,递归结束,输出排序数组
    if(arry.length<=1){
        return arry;
    }
    let leftArry=[],rightArry=[],middleIndex,middleValue;
    //取数组中间项作为参照值
    middleIndex = Math.floor(arry.length/2);
    middleValue = arry.splice(middleIndex,1)[0];
    //比参考值小的放入左边的数组,比参考值大的放入右边的数组
    for(let i=0;i<arry.length;i++){
        arry[i]<middleValue?leftArry.push(arry[i]):rightArry.push(arry[i]);
    }
    //递归方式,直到两边的数组都排好序
    return quickArray(leftArry).concat(middleValue,quickArray(rightArry));
}
console.log(quickArray([12,8,24,16,1]));

数组扁平化

let arr = [
    [1, 2, 2],
    [3, 4, 5, 5],
    [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10
];

描述:将arr 数组处理成一维数组,如下:

arr=> [1,2,2,3,4,5,5,6,7,8,9,11,12,12,13,14,10]


1、ES6真香系列😋

arr.flat(Infinity) ==>

2、转字符串

    let thinArray = arr.toString().split(',').map(item=>{
       return parseFloat(item);
    });

3、使用JSON.stringify()

    let thinArray = JSON.stringify(arr).replace(/\[|\]/g,'').split(',').map(item=>{
        return parseFloat(item);
    });

4、基于数组some方法,如果是数组,我们就[].concat()

    while(arr.some(item=>Array.isArray(item))){
        arr = [].concat(...arr);
    }

5、自己递归处理

~ function(){
    function myFlat(){
        let result = [],
            _this=this;

        let fn = (arr)=>{
            for(let i=0;i<arr.length;i++){
                if(Array.isArray(arr[i])){
                    fn(arr[i]);
                    continue;
                }
                result.push(arr[i]);
            }
        };
        fn(_this);
        return result;
    }
    Array.prototype.myFlat = myFlat;
}();

let arr = [
    [1, 2, 2],
    [3, 4, 5, 5],
    [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10
];
console.log(arr.myFlat());

加餐😆😆阿里面试题之斐波那契数列

请实现一个fibonacci 函数,要求实现以下的功能: 
斐波那契数列为:[1,1,2,3,5,8,13,21,…] 
fibonacci(0) -> 1 
fibonacci(4) -> 5 
……

思路分析:

根据斐波那契数列特点,数组的第一项与第二项都是1,从第三项开始,第N项是N-1项与N-2项之和,所以很容易得出f(n) = f(n-1)+f(n-2);

function FibonacciArray(num){
    if(num<2){
        return 1;
    }else{
        return FibonacciArray(num-1)+FibonacciArray(num-2);
    }
}

加餐🤣🤣字节跳动算法题

 * 输入一个正数N,输出所有和为N的连续正数序列
 * 例如:输入15
 * 结果:[[1,2,3,4,5],[4,5,6],[7,8]]

思路分析:

正数N的二分之一,向上取整得到M, M + (M+1) >N 🤡 ,所以 M + (M-1)<=N 🤓; 我们需要尝试从1开始相加:

1+2+3+...

2+3+4+...

....

M+(M-1)<=N

连续正数序列累加 公式:



 function createArr(n,len){
     let arr =[];
    for(let i=0;i<len;i++){
        arr.push(n+i);
    }
    return arr;
}

function fun(n){
    let result = [];
    let middleValue = Math.ceil(n/2);
    //从i开始累加
    for(let i =1;i<=middleValue;i++){
        //累加的次数
        for(let j=2;;j++){
            let total = i*j+j*(j-1)/2;

            if(total>n){
                break;
            }else if(total===n){
                result.push(createArr(i,j));
                break;
            }
        }
    }

    return result;
}

console.log(fun(15));

结语

如果你看到了这里,说明你离成功又近了一点!加油!

明人不说暗话,我想要一个赞👍!谢谢~😘