如何用数组中返回的元素来记住递归collat​​z函数?

时间:2018-12-23 23:47:19

标签: javascript recursion memoization

我有一个记忆功能,它将记忆返回一个总和的递归函数,例如Number,但是我的collat​​z函数却不返回一个数组。备忘录功能中的我的地图将具有不同的键,但具有相同的值,并且不会记忆该功能的每个步骤。我正在尝试使其尽可能地组合。

控制台在collat​​z中记录日志以检查它是否已运行将按预期第一次注销。

我已经在指数递归函数中对此进行了测试,并使用了另一个可以正确记忆的键盘生成器函数。

const memoized = (fn, keymaker = JSON.stringify) => {
    const lookupTable = new Map();
    return function (...args) {
      const key = keymaker.call(this, args);
      return lookupTable[key] || (lookupTable[key] = fn.apply(this, args));
    }
  };

  const ignoreOthers = ([...values])=>{
    return JSON.stringify(values.shift())
  }


  const memCollatz = memoized((n,arr=[]) =>{
    //console.log('ran')
    if (n<=1) return arr.concat(1)
    else if(n %2 === 0) return memCollatz(n / 2,arr.concat(n))
    else return memCollatz((n*3)+1,arr.concat(n))
  },ignoreOthers)

  console.log(memCollatz(5))
  console.log(memCollatz(6))
  console.log(memCollatz(6))

   
/*
   Map {
    '1': [ 5, 16, 8, 4, 2, 1 ],
    '2': [ 5, 16, 8, 4, 2, 1 ],
    '3': [ 5, 16, 8, 4, 2, 1 ],
    '4': [ 5, 16, 8, 4, 2, 1 ],
    '5': [ 5, 16, 8, 4, 2, 1 ],
    '6': [ 5, 16, 8, 4, 2, 1 ],
    '8': [ 5, 16, 8, 4, 2, 1 ],
    '10': [ 5, 16, 8, 4, 2, 1 ],
    '16': [ 5, 16, 8, 4, 2, 1 ] } 
 */

运行上述控制台日志后,这就是我的地图,但是应该n作为键并记住每个步骤。

1 个答案:

答案 0 :(得分:0)

由于您在memCollat​​z中构建arr的方式,代码执行将如下所示:

memCollatz(5) | arr = [] | map is empty
memCollatz(16) | arr = [5] | map is empty
memCollatz(8) | arr = [5, 16] | map is empty
memCollatz(4) | arr = [5, 16, 8] | map is empty
memCollatz(2) | arr = [5, 16, 8, 4] | map is empty
memCollatz(1) | arr = [5, 16, 8, 4, 2] | map is empty

对memCollat​​z(1)的最后一次调用是第一个实际返回内容的调用,因此

{1: [5, 16, 8, 4, 2, 1]}

已添加到查找图

现在,因为memCollat​​z(2)仅返回了返回的任何memCollat​​z(1),所以另一个 条目

{2: [5, 16, 8, 4, 2, 1]}

已添加到地图

同样,因为memCollat​​z(4)仅返回了返回的任何memCollat​​z(2),所以另一个条目

{4: [5, 16, 8, 4, 2, 1]}

已添加到地图

...等等。

要解决此问题,您需要避免这种“直通”行为,即确保memCollat​​z(1)返回与memCollat​​z(2)不同的内容,等等。

这是一个例子:

  const memCollatz = memoized((n) =>{
    if (n<=1) return [1];
    else if(n %2 === 0) return [n].concat(memCollatz(n / 2))
    else return [n].concat(memCollatz((n*3)+1))
  },ignoreOthers)