likes
comments
collection
share

介绍一个面试常考的数据扁平化方法:阶乘...reduce...

作者站长头像
站长
· 阅读数 48

前言

今天给大家介绍一下一种数学运算方法,阶乘。将这个方法运用到我们面试常常遇见的数据扁平化中。

阶乘是数学中的一种运算。对于非负整数 n,n 的阶乘表示为 n!,它等于从 1 到 n 的所有整数的乘积。

即 n!=1×2×3×······×(n-1)×n。

例如,5 的阶乘 5!=1×2×3×4×5=120。

以下代码都采用JavaScript语言,语言不重要,掌握了方法,任何语言都可以做。

正常阶乘

正常思路:

  1. 初始值为1
  2. 从2开始,×1没意义
  3. 返回最终res
// 阶乘
function mul(n) {
    let res = 1; // 初始值
    for (let i = 2; i <= n; i++) {
        res *= i;
    }
    return res;
}

console.log(mul(5));

递归阶乘(规则一:找公式)

  1. 5的阶乘就是5×4的阶乘,我多么想知道4的阶乘...3的...2的...1的阶乘是多少
  2. mul(5) = 5 * mul(4) = 5 * (4 * mul(3)) = 5 * (4 * (3 * mul(2)))
  3. 由此得到mul(n) = n * mul(n - 1)
function mul(n) {
    return n * mul(n - 1);
}

console.log(mul(5)); // 120

介绍一个面试常考的数据扁平化方法:阶乘...reduce...

  • 第五层返回1
  • 第四层得到第五层的1,返回2*1--->2
  • 第三层得到第四层的2,返回6
  • 第二层得到第三层的6,返回24
  • 第一层得到第二层的24,返回120

代码写到这里,肯定还没结束,一直这么下去无限循环总有一天会爆栈

因此,到此,递归规则一:找公式

递归阶乘(规则二:找出口)

找到一个能出去的口子,当到1的时候该结束了,就不需要进入第六层了。

function mul(n) {
    if (n === 1) return 1;

    return n * mul(n - 1);
}

console.log(mul(5)); // 120

看到这里,大家可以思考一个问题了:

既然阶乘的性能这么差为什么还要用?

  1. 数学理论和概念:阶乘是许多数学理论和公式的基础组成部分,对于理解组合数学、概率统计等领域的基本原理不可或缺。
  2. 特定问题建模:在一些特定的数学模型和实际问题中,阶乘能够准确地描述和解决相关情境,比如排列组合问题。
  3. 逻辑和结构体现:它体现了一种特定的计数逻辑和数学结构,有助于深入分析和理解某些复杂的数学关系。

举一个例子:斐波那契数列。

斐波那契数列

1 1 2 3 5 8 13 21 24 ...

第一位第二位默认为1

fb(10) = fb(9) + fb(8)

公式:fb(n) = fb(n-1) + fb(n-2)

function fb(n) {
//公式
    return fb(n-1) + fb(n-2);
}

console.log(fb(10));

出口?第一位第二位默认为1,因此出口:

function fb(n) {
//出口
    if(n == 1 || n==2) return 1;
    //公式
    return fb(n-1) + fb(n-2);
}

console.log(fb(10));

面试必问:数据扁平化

如何把一个多维数组变成一维的?

es6之后为我们打造了一个flat方法,传参传几就转几次,这里有两层,因此传2

const arr = [1, 2, [3, 4, [5]]]

// 多维数组变成一维数组(扁平化)
const newArr = arr.flat(2)
console.log(newArr);

这时大家想象一个场景,很多时候公司需要通过其他渠道获取数据,但是这个数据到底长什么样,后端朋友自己也不知道,因此你说这个flat传几?他到底有几层?

const arr = [1, 2, [3, 4, [5]]]

// 多维数组变成一维数组(扁平化)
const newArr = arr.flat(Infinity)
console.log(newArr);
  • infinity无穷大

那么如果面试官问你,不用官方打造好的方法,你怎么实现扁平化呢?

const arr = [1, 2, [3, 4, [5]]]

// 多维数组变成一维数组(扁平化)
function flatten(arr){

}

const newArr = flatten(arr)
console.log(newArr)

如何实现自己的flatten方法?

  • 知识点1:数组合并:let allArr = arr.concat(arr2)
  • 知识点2:解构:let arr3 = [1,2,3,4] let[a,b,..c] = arr3,此时a,b就是1,2
  • 知识点3:运用解构,掏出数组里的值:let newArr = [...arr,...arr2],这样就把两个数组的值全部掏出来合并成了一个新数组
const arr = [1, 2, [3, 4, [5]]]

// 多维数组变成一维数组(扁平化)
function flatten(arr) {
    let res = [] // 第一层[1,2] 第二次:[3,4]   第三次:[5]

    for (let i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
            // 找公式找规律:不是数组就push进去res,是数组就递归重来,把这个数组里不是数组的给push
            res = res.concat(flatten(arr[i])) // 三次数组合并
        } else {
            res.push(arr[i])
        }
    }
    return res;

}

const newArr = flatten(arr)
console.log(newArr)

或者用解构

const arr = [1, 2, [3, 4, [5]]]

// 多维数组变成一维数组(扁平化)
function flatten(arr) {
    let res = [] // 第一层[1,2] 第二次:[3,4]   第三次:[5]

    for (let i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
            // 找公式找规律:不是数组就push进去res,是数组就递归重来,把这个数组里不是数组的给push
            // res = res.concat(flatten(arr[i])) // 三次数组合并
            res = [...res, ...flatten(arr[i])]
        } else {
            res.push(arr[i])
        }
    }
    return res;

}

const newArr = flatten(arr)
console.log(newArr)

接下来再介绍一种数据扁平化的办法(取巧,数组中只有数字的情况)

const arr = [1, 2, [3, 4, [5]]]

let str = arr.toString()
console.log(str);
const newArr = str.split(',').map((item) => {
    return Number(item)
})
console.log(newArr);

数组扁平化除了上述toString、flat、递归等办法外,面试官其实更想听到:reduce()

let arr = [1, 2, 3, 4, 5, 6, 7]

let sum = arr.reduce(function (pre, item, index, arr) {
    return pre + item
}, 0)
console.log(sum);
  • reduce方法中接受4个参数,pre是上一次return的结果,如果没有,则为自己传的,这里是0
  • item是里面的每一个值
  • 每一个下标
  • 原数组
  • 因此reduce经常用作累加 介绍完reduce之后,我们来运用以下reduce方法
const arr1 = [1, 2, 'abc', [3, 4, [5]]]
function flatten(arr) {
    return arr.reduce((pre, item) => {
        // 判断item是否为数组,不是数组就可以放到我们传入参数的数组中,否则递归
        return pre.concat(Array.isArray(item) ? flatten(item) : item)
    }, [])
}
console.log(flatten(arr1));

当我们和面试官说完前面的方法之后,再和面试官说我们可以优化以下,用这个reduce方法,然后你一顿dbd,面试官:wowwowow,小伙子对js很熟悉嘛。

此时面试官:还有嘛??? 你....

你... 你别说 还真有!

  • 知识点1:数组中的some方法:判断数组中是否有满足条件的值,有则true,没有false。
  • 知识点2:every,每一个都满足吗?
  • [].concat(1)结果[1]
  • [].cancat([1])结果[1]
  • [].cancat([1,2,[3]])结果[1,2,[3]]
  • 数组cancat一个数字,结果是把数字拼接到数组中,数组concat一个数组,就是把数组中的内容拿出来拼接
const arr1 = [1, 2, 'abc', [3, 4, [5]]]
function flatten(arr1) {
    // 只有数组中还有一项的类型是数组,那就继续循环
    while (arr1.some(item => Array.isArray(item))) {
        arr1 = [].concat(...arr1)

    }
    return arr1;
}
console.log(flatten(arr1));

面试官:优雅...优雅...

小结

在这篇文章中,我们重点讲了面试常考的一个点:数据扁平化,介绍了阶乘,并且介绍了数组合并的几个方法,以及一些优化办法reduce、some...

转载自:https://juejin.cn/post/7371297065740648475
评论
请登录