【问题标题】:JavaScript Algorithms question: how do I use recursion to solve such a combination problem?JavaScript 算法问题:如何使用递归来解决这样的组合问题?
【发布时间】:2021-06-14 07:25:10
【问题描述】:

我们有一个看起来像这样的数字字母图

const digitsLetters = new Map([
    ["2", ['a', 'b', 'c']],
    ["3", ['d', 'e', 'f']],
    ["4", ['g', 'h', 'i']],
    ["5", ['j', 'k', 'l']],
    ["6", ['m', 'n', 'o']],
    ["7", ['p', 'q', 'r', 's']],
    ["8", ['t', 'u', 'v']],
    ["9", ['w', 'x', 'y', 'z']],
  ]);

问题要求我们返回数字可以代表的所有可能的字母组合。例如,如果我们有"23",那么第一个数字2 映射到['a', 'b', 'c'],第二个数字映射到['d', 'e', 'f'],我们最终得到["ad","ae","af","bd","be","bf","cd","ce","cf"]

我找到了一种在两个数组之间产生这种组合的方法。

// this will output ["ad","ae","af","bd","be","bf","cd","ce","cf"]
['a', 'b', 'c'].map(char1 => ['d', 'e', 'f'].map(char2 => char1 + char2)).flat(2)

所以我想我可以递归地将此算法应用于这样的数字,直到我找到最后一个。我认为这是可行的。但是,我很难实施该解决方案。有人可以帮我吗?

【问题讨论】:

  • 是的,可以使用递归。我建议将maps 扁平化为for 循环,然后看看您是否可以从那里弄清楚如何创建递归公式。我认为这可能会让你更清楚。

标签: javascript algorithm recursion


【解决方案1】:

让我们用一个例子来考虑笛卡尔积f(E, F)

假设E 就像['12', '13']

然后你会得到候选人ab,我将它们命名为F = ['a', 'b']

f(E, F) = E x F 会给['12a', '13a', '12b', '13b']

(注意ExFE是同一种类型,一个字符串数组)

现在你可以递归给定的数字

g([digit, ...otherDigits], E) => {
  candidates = m.get(digit)
  EF = cartesianProduct(E, candidates)
  return g(otherDigits, EF)
}

注意E上的初始化不应该是空数组,而是长度为1的数组,其唯一元素是“中性”元素(字符串为空字符串)

const data = new Map([
  ["2", ['a', 'b', 'c']],
  ["3", ['d', 'e', 'f']],
  ["4", ['g', 'h', 'i']],
  ["5", ['j', 'k', 'l']],
  ["6", ['m', 'n', 'o']],
  ["7", ['p', 'q', 'r', 's']],
  ["8", ['t', 'u', 'v']],
  ["9", ['w', 'x', 'y', 'z']],
]);
const f = (E, F) => E.flatMap(e => F.map(f => e + f))
const g = ([digit, ...otherDigits], E=['']) => digit ? g(otherDigits, f(E, data.get(digit))) : E
console.log(g('23'.split('')))
console.log(g('234'.split('')))

【讨论】:

    【解决方案2】:

    您基本上可以使用map 方法从您Map 基于字符串参数的数据中获取数组,它们实现笛卡尔积算法。

    const data = new Map([
      ["2", ['a', 'b', 'c']],
      ["3", ['d', 'e', 'f']],
      ["4", ['g', 'h', 'i']],
      ["5", ['j', 'k', 'l']],
      ["6", ['m', 'n', 'o']],
      ["7", ['p', 'q', 'r', 's']],
      ["8", ['t', 'u', 'v']],
      ["9", ['w', 'x', 'y', 'z']],
    ]);
    
    function f(str, map) {
      const result = [];
      const arr = str.split('').map(c => map.get(c))
    
      function r(data, n = 0, prev = []) {
        if (n === data.length) {
          return result.push(prev.slice())
        }
    
        for (let i = 0; i < data[n].length; i++) {
          prev[n] = data[n][i]
          r(data, n + 1, prev.slice())
        }
      }
    
      r(arr)
    
      return result;
    }
    
    console.log(f('23', data))
    console.log(f('358', data))

    【讨论】:

      【解决方案3】:

      类似的东西

      const digitsLetters = new Map([
        ["2", ['a', 'b', 'c']],
        ["3", ['d', 'e', 'f']],
        ["4", ['g', 'h', 'i']],
        ["5", ['j', 'k', 'l']],
        ["6", ['m', 'n', 'o']],
        ["7", ['p', 'q', 'r', 's']],
        ["8", ['t', 'u', 'v']],
        ["9", ['w', 'x', 'y', 'z']],
      ]);   
      
      const foo = (arr, result = []) => {
        if (arr.length === 0) return result;
        
        const value = arr.shift();
        if (result.length === 0) return foo(arr, value);
       
        const newResult = [];
        
        result.forEach((el) => {
          value.forEach((el2) => {
            newResult.push(el + el2);
          });
        });
      
        return foo(arr, newResult);  
      };
      
      const boo = (str) => foo(str.split('').map((symbol) => (digitsLetters.get(symbol))));
      
      console.log(boo(''));
      console.log(boo('2'));
      console.log(boo('23'));
      console.log(boo('232'));

      【讨论】:

        猜你喜欢
        • 2020-03-26
        • 2011-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-11
        • 2011-03-20
        • 1970-01-01
        相关资源
        最近更新 更多