1.概括
所谓记忆化搜索是指将已经计算过的数值记录下来,当作一个状态,当再次访问到这个状态时直接返回这个值,减少计算的时间以降低时间复杂度。
使用记忆化搜索要注意重复计算的值要相同,以防数据失真;
2.代码与解释(以斐波那契数列为例)
一般面对与斐波那契数列相似的问题时我们会使用到递归,即当输入的值大于等于2的时候我们会返回n-1与n-2的值,不断累加,最后求得答案。但是当数据多的时候会面临一段时间复杂度为o(N^2)的代码。
回顾整个递归的过程我们会发现有多个数据(比如f(3)和f(4))被多次计算,所以我们试想如果我们将已经计算过的数据记录下来,当需要此值时直接调用那么是不是会减少时间复杂度?
#include"bits/stdc++.h"
using namespace std;
using ll = long long;
const int N = 1e5 + 3;
ll dp[N];
ll f(int n)
{
if(n<=2)return 1;
if(dp[n]!=-1) return dp[n];//如果dp[n]已经被计算过,直接返回
return dp[n]=f(n-1)+f(n-2);//dp[n]没有数据那么录入当斐波那契数列为n时的数据
}
int main()
{
memset(dp, -1,sizeof dp);//将dp数组初始化,使其值全为1
int n;cin>>n;
cout<<f(n)<<'\n';
return 0;
}
这里我们定义了一个dp数组来计算f(n)的值,当查询到dp[n]已经被计算过,那么不需要再计算接下来的递归,只需要直接返回这个值。与普通递归一样计算f(6),我们计算f(5)后会记录下f(4)与f(3)的值当计算后面的f(4)时只需要直接返回记录的f(4)的值,即dp[4]。
该问题还可以用动态规划完成,但两者不等同。