介绍一个面试常考的数据扁平化方法:阶乘...reduce...
前言
今天给大家介绍一下一种数学运算方法,阶乘。将这个方法运用到我们面试常常遇见的数据扁平化中。
阶乘是数学中的一种运算。对于非负整数 n,n 的阶乘表示为 n!,它等于从 1 到 n 的所有整数的乘积。
即 n!=1×2×3×······×(n-1)×n。
例如,5 的阶乘 5!=1×2×3×4×5=120。
以下代码都采用JavaScript语言,语言不重要,掌握了方法,任何语言都可以做。
正常阶乘
正常思路:
- 初始值为1
- 从2开始,×1没意义
- 返回最终res
// 阶乘
function mul(n) {
let res = 1; // 初始值
for (let i = 2; i <= n; i++) {
res *= i;
}
return res;
}
console.log(mul(5));
递归阶乘(规则一:找公式)
- 5的阶乘就是5×4的阶乘,我多么想知道4的阶乘...3的...2的...1的阶乘是多少
- mul(5) = 5 * mul(4) = 5 * (4 * mul(3)) = 5 * (4 * (3 * mul(2)))
- 由此得到mul(n) = n * mul(n - 1)
function mul(n) {
return n * mul(n - 1);
}
console.log(mul(5)); // 120
- 第五层返回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 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