[js] 记忆(memoization) 斐波那契数列(Fibonacci sequence)
#
var result = []; function fn(n) { //典型的斐波那契数列 if (n == 1) { return 1; } else if (n == 2) { return 1; } else { if (result[n]) { //缓存 return result[n]; } else { result[n] = arguments.callee(n - 1) + arguments.callee(n - 2); return result[n]; } } }
#
var fibonacci1 = function(n) { return n < 2 ? n : fibonacci1(n - 1) + fibonacci1(n - 2); }; // var fibonacci = function(n) { // return n < 2 ? n : arguments.callee(n - 1) + arguments.callee(n - 2); // }; for (var i = 0; i <= 10; i += 1) { console.log('// ' + i + ': ' + fibonacci1(i)); } //本身被调用了453次 // 0: 0 // 1: 1 // 2: 1 // 3: 2 // 4: 3 // 5: 5 // 6: 8 // 7: 13 // 8: 21 // 9: 34 // 10: 55
#
//fibonacci 调用优化 //只调用29次 var fibonacci2 = (function() { var memo = [0, 1]; var fib = function(n) { var result = memo[n]; if (typeof result !== 'number') { result = fib(n - 1) + fib(n - 2); memo[n] = result; } return result; }; return fib; }()); for (var i = 0; i <= 10; i += 1) { console.log('// ' + i + ': ' + fibonacci2(i)); }
#
var mFib = function() { var cache = [1, 1]; // 裴波拉契数的前两个数为1, 1 return function(m) { var len = cache.length, i = len; // 如果m大于cache的长度, 则说明m对应的裴波拉契数不存在, 需要计算 if (m > len) { // 当i等于m的时候, 小于i之前的裴波拉契数已经计算过了, 可以直接使用 // 有的例子用的for循环, 但while循环更快 while (i <= m) { // 裴波拉契数的特点, 后一个数等于前两个数之和 // 把计算结果缓存起来, 避免再次计算 cache[i] = cache[i - 2] + cache[i - 1]; i++; } } // 当裴波拉契数存在时, 直接使用 return cache[m - 1]; } }();
#
//进而产生通用的优化方案 var memoizer = function(memo, formula) { var recur = function(n) { var result = memo[n]; if (typeof result !== 'number') { result = formula(recur, n); memo[n] = result; } return result; }; return recur; }; var fibonacci = memoizer([0, 1], function(recur, n) { return recur(n - 1) + recur(n - 2); }); for (var i = 0; i <= 10; i += 1) { console.warn('// ' + i + ': ' + fibonacci(i)); } var factorial = memoizer([1, 1], function(recur, n) { return n * recur(n - 1); }); for (var i = 0; i <= 10; i += 1) { console.warn('// ' + i + ': ' + factorial(i)); }
浙公网安备 33010602011771号