Q: 函数记忆是什么?什么场景下使用?(动态规划)
A:
01,将上次计算结果保存起来的函数,称为有记忆能力(memorization)的函数。
function memorize(f) {
var cache = {};
return function() {
var key = arguments.length + Array.prototype.join.call(arguments,",");
if (key in cache) return cache[key];
else return cache[key] = f.apply(this, arguments);
};
}
- 01,利用闭包,将结算结果保存在私有的缓存对象里。
- 02,将实参长度加实参参数作为缓存对象属性。
- 03,如果key属性不存在,就将结果保存在key属性的值。
下面的代码展示了如何使用memorize():
// 返回两个整数的最大公约数
// 使用欧几里德算法:http://en.wikipedia.org/wiki/Euclidean_algorithm
function gcd(a,b) { // 这里省略对a和b的类型检查
var t; // 临时变量用来存储交换数值
if (a < b) t=b, b=a, a=t; // 确保 a >= b
while(b != 0) t=b, b = a%b, a=t; // 这是求最大公约数的欧几里德算法
return a;
}
var gcdmemo = memorize(gcd);
gcdmemo(85, 187) // => 17
代码分析By魔芋
var gcdmemo = memorize(gcd);
f=gcd(a,b);
第一次调用时,cache为空对象。 gcdmemo为返回的匿名函数。
key为285,187
第二次调用时,cache.key已存在,将直接返回计算值。
应用一:实现记忆功能的递归函数:
var factorial = memorize(function(n) {
return (n <= 1) ? 1 : n * factorial(n-1);
});
factorial(5) // => 120.对于4~1的值也有缓存
应用二:数组去重:
unction unique(arr) {
var ret = []
var hash = {}
for (var i = 0; i < arr.length; i++) {
var item = arr[i]
var key = typeof(item) + item;
if (hash[key] !== 1) {
ret.push(item)
hash[key] = 1
}
}
return ret;
}
**