文章目录
- 前言
- 动态规知识点
- 动规五部曲
- 一、647. 回文子串
- 二、516. 最长回文子序列
- 总结
前言
一个本硕双非的小菜鸡,备战24年秋招,计划二刷完卡子哥的刷题计划,加油!
二刷决定精刷了,于是参加了卡子哥的刷题班,训练营为期60天,我一定能坚持下去,迎来两个月后的脱变的,加油!
推荐一手卡子哥的刷题网站,感谢卡子哥。代码随想录
动态规知识点
终于来到了守关boss。。。
动态规划中每一个状态一定是由上一个状态推导出来的
动规是由前一个状态推导出来的,而贪心是局部直接选最优的。
动规五部曲
动态规划一般分为如下五步:
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
//1. 确定dp数组(dp table)以及下标的含义//2. 确定递推公式//3. dp数组如何初始化//4. 确定遍历顺序//5. 举例推导dp数组
解题时候多把dp数组打印出来,看看究竟是不是按照自己思路推导的。
写代码之前一定要把状态转移在dp数组的上具体情况模拟一遍,心中有数,确定最后推出的是想要的结果。
然后再写代码,如果代码没通过就打印dp数组,看看是不是和自己预先推导的哪里不一样。
如果打印出来和自己预先模拟推导是一样的,那么就是自己的递归公式、初始化或者遍历顺序有问题了。
如果和自己预先模拟推导的不一样,那么就是代码实现细节有问题。
一、647. 回文子串
647. 回文子串
Note:反向遍历,三种情况
class Solution {
public:int countSubstrings(string s) {//1. 确定dp数组(dp table)以及下标的含义//布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));int res = 0;//2. 确定递推公式//当s[i]与s[j]不相等,dp[i][j] = false;/*当s[i]与s[j]相等:情况一:下标i 与 j相同,同一个字符例如a,当然是回文子串情况二:下标i 与 j相差为1,例如aa,也是回文子串情况三:下标:i 与 j相差大于1的时候,例如cabac,此时s[i]与s[j]已经相同了,这个区间是不是回文就看dp[i + 1][j - 1]是否为true。*///3. dp数组如何初始化//4. 确定遍历顺序for (int i = s.size() - 1; i >= 0; i--) {for (int j = i; j < s.size(); j++) {if (s[i] == s[j]) {if (j - i <= 1) {res++;dp[i][j] = true;} else if (dp[i + 1][j - 1]) {res++;dp[i][j] = true;}}}}//5. 举例推导dp数组return res;}
};
二、516. 最长回文子序列
516. 最长回文子序列
Note:动规最后一题,仍需努力
class Solution {
public:int longestPalindromeSubseq(string s) {// 1. 确定dp数组(dp table)以及下标的含义// dp[i][j]:字符串s在[i, j]范围内最长的回文子序列的长度为dp[i][j]。vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));// 2. 确定递推公式/*if (s[i] == s[j]) dp[i][j] = dp[i + 1][j - 1] + 2;else dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);*/// 3. dp数组如何初始化for (int i = 0; i < s.size(); i++)dp[i][i] = 1;// 4. 确定遍历顺序for (int i = s.size() - 1; i >= 0; i--) {for (int j = i + 1; j < s.size(); j++) {if (s[i] == s[j]) {dp[i][j] = dp[i + 1][j - 1] + 2;} else {dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);}}}// 5. 举例推导dp数组return dp[0][s.size() - 1];}
};
总结
动态规划法,和分治法极其相似。区别就是,在求解子问题时,会保存该子问题的解,后面的子问题求解时,可以直接拿来计算。