【问题标题】:Memoize my recursive coinSums记住我的递归 coinSums
【发布时间】:2023-03-28 19:17:01
【问题描述】:

我有一个基本的coinSums递归函数:

function coinSums(total) {      
    var coins = [1, 5, 10, 25];
    var output = [];
    var memo={} <--the only part im sure about :)
    function subroutine(pos, runningSum, currentCombo) {
        if (total === runningSum) {
            return output.push(currentCombo)
        } else if (total < runningSum) {
            return false
        } else
            for (var i = pos; i < coins.length; i++) {
                subroutine(i, runningSum + coins[i], currentCombo.concat(coins[i]))
            }
    }
    subroutine(0, 0, [])
    return output.length; }

我真的很想找到一种“记忆”它的方法来改进 O(n^k) 运行时(k=num of coinsn=target,对吗?),但请保留它 递归而不是尽可能少地改变递归调用。 (我需要保持组合和runningSum 自下而上 方法)。

我知道如何使用自上而下的方法。任何天才 有什么想法吗?

ps 我们可以在for 循环中将pos 更改为i 从 0 开始,为我们提供有序组合的数量。我需要 返回无序的组合,这就是我要维护的原因 连击。

【问题讨论】:

  • 请注意,记忆化是动态编程中的一项基本技术,如果之前使用相同的参数调用它,它可以防止递归。您提到更喜欢保留递归,但它不会是动态编程。
  • 我不知道整个问题,但我认为你应该使用Bit Masking 方法来解决这个问题。
  • 1.如果你正在寻找记忆,这里是链接addyosmani.com/blog/faster-javascript-memoization 2。在 JS 中,函数也是一个对象,所以你不必声明一个新对象来缓存值。相反,您可以使用 functionName[input] 来存储当前输入的输出。 3. var memo = {} 是一个对象,用于存储/缓存特定输入的结果。

标签: javascript recursion dynamic-programming memoization


【解决方案1】:

这是一种使用动态规划的方法。有关该方法的更多详细信息,请观看此视频https://www.youtube.com/watch?v=jaNZ83Q3QGc

function coinsSum(amount) {
  const coins = [1, 5, 10, 25]
  const combinations = Array(amount + 1).fill(0);
  combinations[0] = 1;
  let count = 0;
  while (count < coins.length) {
    const coin = coins[count];
    for (let i = coin; i < combinations.length; i++) {
      if (amount >= coin) combinations[i] += combinations[i - coin];
    }
    count++;
  }
  return combinations.pop();
}

【讨论】:

    【解决方案2】:

    恐怕您的要求无法满足,除非您想将 memoization 用于多种用途 coinSums 本身——在前者的单个应用程序中,您正在调用 subroutine always 不同的参数集,使它们独一无二的是currentCombo,我认为在记忆时不能“抽象”,因为它是整个算法的核心......

    你可以做的是用自上而下的递归收集这个 output 东西,这对于记忆来说“很好”,尽管这可能是你已经知道的......

    function coinSums(total) {
        /// "cache":
        var _coinSumsMem_ = {};
        var lookupCoins = function(total,pos) {
            return _coinSumsMem_[[total,pos]];
        };
        var memoizeCoins=function(total,pos, coins) {
            _coinSumsMem_[[total,pos]]
                = coins.map(function(xs) {return xs.slice();}); /// a clone!
        };
        /// "computation":
        var coinsAvailable = [1,5,10,20];    
        findAll = function(total, pos) {
            if(total<0 || pos==coinsAvailable.length) return [];
            else if(total==0) return [[]];
            var result = lookupCoins(total,pos);
            if(result == undefined) {
                var oneWaySums = findAll(total-coinsAvailable[pos], pos);
                oneWaySums.map(function(xs) {xs.push(coinsAvailable[pos]);});
                var otherWaySums = findAll(total, pos+1);
                result = oneWaySums.concat(otherWaySums);
                memoizeCoins(total,pos, result);
            }
            return result;
        };
        return findAll(total,0).length; /// or without length...
    }
    

    【讨论】:

      猜你喜欢
      • 2018-10-07
      • 2020-10-11
      • 2015-08-09
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 2017-09-19
      • 1970-01-01
      相关资源
      最近更新 更多