【问题标题】:Javascript - Better Alternate to Recursive callJavascript - 更好地替代递归调用
【发布时间】:2017-06-04 02:07:07
【问题描述】:

我有以下问题。 我需要根据时间 t 计算一个数字 x,x 将表示为 M(t)。 我们有以下

  • M(0) = 1
  • M(1) = 1
  • M(2) = 2
  • M(2t) = M(t) + M(t + 1) + t(对于 t > 1)
  • M(2t + 1) = M(t - 1) + M(t) + 1(对于 t >= 1)

话虽如此,我首先想到的是使用递归

function CalculateForTime(t) {
    if (t == 0 || t == 1) {
        return 1;
    }
    else if (t == 2) {
        return 2;
    }
    else if (t % 2 == 0) {
        t = t / 2;
        return CalculateForTime(t) + CalculateForTime(t + 1) + t;
    }
    else {
        t = (t - 1) / 2;
        return CalculateForTime(t - 1) + CalculateForTime(t) + 1;
    }
}

这可行,但是在运行大数 t 时会中断,例如 1^20

我尝试研究尾调用递归或将递归方法替换为迭代方法,但无法真正弄清楚。

如果尾递归或迭代是可行的方法,那么我需要帮助来转换它。如果没有,那么我愿意采用不同的方法来优化它。

谢谢, 奥马尔。

【问题讨论】:

    标签: javascript performance recursion optimization


    【解决方案1】:

    您可以使用哈希表,因为对于数组,它会生成没有值的空洞。

    function calculateForTime(t) {
        var k = t;
        if (k in lookup) {
            return lookup[k];
        }
        if (t == 0 || t == 1) {
            return lookup[k] = 1;
        }
        if (t == 2) {
            return lookup[k] = 2;
        }
        if (t % 2 == 0) {
            t = t / 2;
            return lookup[k] = calculateForTime(t) + calculateForTime(t + 1) + t;
        }
        t = (t - 1) / 2;
        return lookup[k] = calculateForTime(t - 1) + calculateForTime(t) + 1;
    }
    
    var lookup = {};
    console.log(calculateForTime(1e10));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    【解决方案2】:

    您可以将值存储在数组中,然后无需重新计算...

    var times=[1,1,2];
    function CalculateForTime(t) {
        t = Math.floor(t / 2);
            return times[t]||(times[t]=CalculateForTime(t) + CalculateForTime(t + 1) + t);
    }
    
    console.log(
    CalculateForTime(100),
    CalculateForTime(1000),
    CalculateForTime(10000),
    );
    console.log(times.slice(0,100));

    【讨论】:

      【解决方案3】:

      您可以使用记忆功能来避免一次又一次地重新计算相同的值。见https://addyosmani.com/blog/faster-javascript-memoization/

      这与其他人建议的相同,只是它将算法与值的缓存分开。

      function memoize(func){ 
          var cache = {}; 
          return function( arg ){ 
               if(arg in cache) {
                   return cache[arg]; 
               } else { 
                   return cache[arg] = func( arg );
               } 
           }
        }
      
        // Overwrite with a function that remember previous results
        CalculateForTime = memoize(CalculateForTime);
      

      如有错别字,请电话回复

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-24
        • 2020-11-18
        • 1970-01-01
        • 1970-01-01
        • 2014-12-17
        • 1970-01-01
        相关资源
        最近更新 更多