分析一道算法题,多维数组的排列组合问题

638 阅读2分钟

「这是我参与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的题目吧,电话号码的字母组合,是不是觉得一毛一样,其实只是多了一层映射关系的转换而已。