一、记忆化搜索是什么?
首先我们来看看百度百科的这句话
一般说来,动态规划总要遍历所有的状态,而搜索可以排除一些无效状态。更重要的是搜索还可以剪枝,可能剪去大量不必要的状态,因此在空间开销上往往比动态规划要低很多。记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下来,以后再次遇到这个状态的时候,就不必重新求解了。这种方法综合了搜索和动态规划两方面的优点,因而还是很有实用价值的。
这便是百度百科给出的记忆化搜索的定义。
我们理解记忆化搜索,可以抓住两个关键词保存
以及不必重新求解
。
以下我们基于这两个关键词谈谈记忆化的流程。
二、记忆化的流程
在这里我们以广为人知的斐波那契数列为例,谈谈记忆化的流程。
int[] q = new int[50000];
public int find(int k){
if(k==0){
return 0;
}
if(k<2){
return 1;
}
if(q[k-1]==0){
q[k-1] = find(k-1);
}
if(q[k-2]==0){
q[k-2] = find(k-2);
}
q[k] = q[k-1]+q[k-2];
//return find(k-1)+find(k-2);
return q[k];
}
1.保存该状态的值
保存该状态的值往往需要一个数组,使用数组的下标记录当前状态的值,例如上面的斐波那契数列就是使用下标记录第x位的斐波那契数列的值。
2.获取该状态的值
由于该状态的值已经被保存在了数组中,我们直接可以通过数组的下标获取当前状态的值
需要注意的是在实际操作中我们在调用该状态的值时往往不能确定它是否已经被计算过,所以我们通常初始化数组中的值为一个不可能得到的一个结果,当当前数组的值不等于初始值时,我们才能直接调用,否则需要先计算该状态的结果,将结果存入数组中,再进行获取操作
总结
这篇文章仅为非正式的介绍一下记忆化搜索,选取的例子为了简单所以具有一定的特殊性,如想更深入的了解记忆化搜索的运行过程。请看我的这篇文章。