Javascript - 更好地替代递归调用

时间:2017-06-03 17:34:00

标签: javascript performance recursion optimization

我遇到以下问题。 我需要根据时间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

我试着调查尾调用递归或用递归方法代替迭代方法,但无法真正弄明白。

如果要进行尾递归或迭代,那么请转换它需要帮助。如果没有,那么我可以采用不同的方法使其更加优化。

谢谢你, 奥马。

3 个答案:

答案 0 :(得分:4)

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

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; }

答案 1 :(得分:0)

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



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));




答案 2 :(得分:0)

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

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

(

请原谅任何错别字,通过电话回答