DP&记忆化通用思路总结
- //DP思想: 寻找与原问题 同类的 更小的子问题
- //确定更小的同类问题: 可以用递归
- //发掘大小问题的通用逻辑: 递归函数写什么
- //递归函数基本构成:
- //确定这个递归函数返回什么结果
- //递归结束条件
- //递归函数主体
- //什么时候用记忆化:
- //存在大量重复计算时 <=> 递归函数参数相同,那么结果必然一样
本题实战代码
初步构建递归 (提交后超时)
class Solution {
public:
//DP思想: 寻找与原问题 同类的 更小的子问题
//更小的同类问题: 可以用递归
//通用逻辑: 递归函数写什么
//递归函数基本构成:
//递归函数返回值
//递归结束条件
//递归函数主体
int minimumSubstringsInPartition(string s) {
int len = s.length();
//确定返回值: s的长度为 i+1 的前缀 最少可以被分隔为多少个平衡子串
auto dfs = [&](auto&& dfs, int i) -> int {
if( i<0 ) return 0;
int res = INT_MAX, k=0, max_num = 0;
int word[26]{};
for(int j=i; j>0; j--)
{
//"从右往左"依次遍历
k += word[s[j] - 'a']++ == 0;
max_num = max(max_num, word[s[j] - 'a']);
if(i-j+1 == k*max_num)
{
res = min(res, dfs(dfs, j)+1);
}
}
return res;
}
return dfs(s.length()-1);
}
};
加入记忆化:
class Solution {
public:
int minimumSubstringsInPartition(string s) {
int len = s.length();
vector<int>memo(len);
//确定返回值: s的长度为 i+1 的前缀 最少可以被分隔为多少个平衡子串
auto dfs = [&](auto&& dfs, int i) -> int {
if( i<0 ) return 0;
if(memo[i]) return memo[i];
int res = INT_MAX, k=0, max_num = 0;
int word[26]{};
for(int j=i; j>0; j--)
{
//"从右往左"依次遍历
k += word[s[j] - 'a']++ == 0;
max_num = max(max_num, word[s[j] - 'a']);
if(i-j+1 == k*max_num)
{
int h = dfs(dfs, j-1);
res = min(res, dfs(dfs, j-1)+1);
}
}
memo[i] = res;
return res;
};
return dfs(dfs, len-1);
}
};
~希望对你有启发!~