「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」
题目背景
我的朋友豪总今天和我讨论了一道面试题目,题目是这样的,给定一个数组 arrays = [["a", "b"],["n", "m"],["0", "1"]],请输出结果[ 'an0', 'an1', 'am0', 'am1', 'bn0', 'bn1', 'bm0', 'bm1' ]
简要分析
首先我们来分析一下这道题意,这是一个多维数组的排列组合,我们来想一下,如果是两个数组的排列组合,是不是暴力双重循环就可以了
const arrays = [
["a", "b"],
["n", "m"],
];
const Combination = (arr1, arr2) => {
const newArr = [];
for (const v1 of arr1) {
for (const v2 of arr2) {
newArr.push(`${v1}${v2}`);
}
}
return newArr;
};
console.log(Combination(arrays[0], arrays[1]));
循环
那这道题我们是不是也可以用for循环解决,代码如下,只不过外层需要多一个循环
function Combination(arr) {
let res = arr[0];
for (let i = 1; i < arr.length; i++) {
const pre = res;
res = [];
pre.forEach((item) => {
arr[i].forEach((curr) => {
res.push(item + curr);
});
});
}
return res;
}
console.log(Combination(arrays));
reduce的方式处理
可以利用reduce让代码简洁一些,其实这也就是笛卡尔积的计算(宇宙的尽头是数学)
function Combination(arr) {
return arr.reduce((pre, cur) => {
if (pre.length === 0) return cur.map((prop) => [prop]);
const preList = [...pre];
const newList = [];
cur.forEach((curItem) => {
preList.forEach((preItem) => {
newList.push(preItem + curItem);
});
});
return newList;
}, []);
}
console.log(Combination(arrays));
深度优先搜索 dfs
可以用深度优先搜索的思路,dfs递归。
const Combination = (arr) => {
const res = [];
const dfs = (curStr, i) => {
if (i > arr.length - 1) {
res.push(curStr);
return;
}
const item = arr[i];
for (const letter of item) {
dfs(curStr + letter, i + 1);
}
};
dfs("", 0);
return res;
};
console.log(Combination(arrays));
回溯 backtracking
换一个思路,可以回溯backtracking
const Combination = (arr) => {
const k = arr.length; //
const res = [],
path = [];
backtracking(arr, 0);
return res;
function backtracking(n, a) {
if (path.length === k) {
res.push(path.join(""));
return;
}
const item = arr[a];
for (const v of item) {
path.push(v);
backtracking(n, a + 1);
path.pop();
}
}
};
console.log(Combination(arrays));
ending举一反三
看完了以上题解,让我们来看一道leetcode的题目吧,电话号码的字母组合,是不是觉得一毛一样,其实只是多了一层映射关系的转换而已。