编码挑战,尝试递归解决。帮助使用Closure进行缓存

时间:2019-02-17 23:04:27

标签: javascript recursion closures

问题: / step(x)操作的工作原理是:将x转换为x-s(x),其中s(x)是x的数字之和。 ///您喜欢对数字应用函数,因此给定数字n,您决定构建一个递减的数字序列:n,step(n), // step(step(n))等,最后一个元素为0。

//建立一个单独的序列对您来说还不够,因此您要用其数字的总和(s(x))替换序列中的所有元素。 //现在,您好奇哪个数字最常出现在新序列中。如果有多个答案,请返回最大答案。

// 示例

//-对于n = 88,输出应为 // mostFrequentDigitSum(n)= 9。

//这是您构建的第一个序列:88、72、63、54、45、36、27、18、9、0;

//这是每个元素的s(x):16、9、9、9、9、9、9、9、9、0。

//如您所见,第二个序列中最频繁的数字是9。

//-对于n = 8,输出应为 // mostFrequentDigitSum(n)= 8。

//首先,您构建了以下序列:8,0

// s(x)的每个元素为:8、0

//如您所见,答案是8(它的出现频率通常为0,但大于0)。

所以我看了这个问题,似乎递归在这里会很好。我敢肯定,有一种迭代的方式可以轻松得多,但是我也想在递归上做得更好,所以我使用递归进行了尝试。

let cache = {}

function recursiveCall ( x ) {
    if( x == 0 ) { return 'dog' } // we dont need to return anything, because after each recursive call we are saving cache[sumOfX] in our cache,
    //once we get to the very TOP of our stack when it hit 0.  We have already made our object, and therefore do not even need a return statement.


    //get the sum of our digits for x.
    let sumOfX = x.toString().split('').map( n => { return Number(n)}).reduce( (sum, num) => {
        sum += num;
        return sum;
    },0);

    //creates a key for a sumOfX and makes the value 1 if it hasnt been seen or increments the value if it has been seen.
    if( !cache[sumOfX] ) {
        cache[sumOfX] = 1;
    } else {
        cache[sumOfX]++;
    }



    console.log(x);
    console.log(sumOfX);
    recursiveCall( x - sumOfX );
    console.log(cache)
}



function mostFrequentDigitSum( digit ) {
//create our cache using our recursive call
recursiveCall(digit);

//find the largest value in that object.
let max = 0;
let value = 0;
for(var key in cache) {
    if( max < cache[key]) {
        max = cache[key];
        value = Number(key);
    }
}
return value;
}


console.log(mostFrequentDigitSum(88));

console.log(cache);

我使用递归创建了一个对象。不过,我必须为缓存创建一个全局变量,并且我希望代码是独立的。我试图做一些事情使它作为一个闭包工作,但仍然没有提出解决方案。任何提示都将有所帮助,因为如果有其他方法可以递归地解决此问题,那么我将尝试更好地进行递归,因此我不会查看其他人的代码。使我的工作递归进行并在一个独立的封闭中也将很有帮助。谢谢。

1 个答案:

答案 0 :(得分:1)

您可以让recursiveCall接受另一个参数cache,该参数默认为{}

function recursiveCall(x, cache = {}) {
  if (x == 0) {
    return cache;
  }
  // ...
  return recursiveCall(x - sumOfX, cache);
}

在第一次调用recursiveCall时,将创建cache对象;在随后对recursiveCall的递归调用中,您可以将该对象作为第二个参数传递。递归结束时,return cache使其返回到初始调用:

function mostFrequentDigitSum(digit) {
  //create our cache using our recursive call
  const cache = recursiveCall(digit);

然后可以使用该cache变量来计算要从value返回的mostFrequentDigitSumcache现在不是全局的,它是在每次调用mostFrequentDigitSum时重新创建的(或更确切地说,是每次在外部调用recursiveCall时都重新创建)。

function recursiveCall(x, cache = {}) {
  if (x == 0) {
    return cache;
  }
  //get the sum of our digits for x.
  let sumOfX = x.toString().split('').map(n => {
    return Number(n)
  }).reduce((sum, num) => {
    sum += num;
    return sum;
  }, 0);

  //creates a key for a sumOfX and makes the value 1 if it hasnt been seen or increments the value if it has been seen.
  if (!cache[sumOfX]) {
    cache[sumOfX] = 1;
  } else {
    cache[sumOfX]++;
  }
  return recursiveCall(x - sumOfX, cache);
}



function mostFrequentDigitSum(digit) {
  //create our cache using our recursive call
  const cache = recursiveCall(digit);

  //find the largest value in that object.
  let max = 0;
  let value = 0;
  for (var key in cache) {
    if (max < cache[key]) {
      max = cache[key];
      value = Number(key);
    }
  }
  return value;
}


console.log(mostFrequentDigitSum(88));

或者,在保持相同逻辑的同时精简代码:

function recursiveCall(x, cache = {}) {
  if (x === 0) {
    return cache;
  }
  const sumOfX = x.toString().split('').map(Number).reduce((a, b) => a + b, 0);
  cache[sumOfX] = (cache[sumOfX] || 0) + 1;
  return recursiveCall(x - sumOfX, cache);
}

function mostFrequentDigitSum(digit) {
  //create our cache using our recursive call
  const cache = recursiveCall(digit);
  //find the largest value in that object.
  return Object.entries(cache).reduce((a, b) => a[1] > b[1] ? a : b, [null, 0])[0];
}
console.log(mostFrequentDigitSum(88));
console.log(mostFrequentDigitSum(8));
console.log(mostFrequentDigitSum(0));