今天下午的第一弹也就是动态规划章节的最后一弹,动态规划终于快要结束了,真的很难,但也是笔试和面试中最常考察的,继续刷题,开冲!!!
今日任务
- 647.回文子串
- 516.最长回文子序列
题目一:647.回文子串
Leetcode题目:【647.回文子串】
如何使用动态规划的方法解决回文子串,按照动规五部曲:
(1)定义dp数组:dp[i][j]:定义i到j的子串是否是回文子串,如果是回文的就是true,反之为false;
(2)确定递推公式:(相同的话是有三种情况的)
if(s[i] == s[j]){
if(j - i <=1) {
dp[i][j] = true;
result++;
}else{
if(dp[i+1][j-1] == true){
dp[i][j] = true;
result++;
}
}
}
(3)初始化:dp[i][j] = false;
(4)遍历顺序:
因为dp[i][j]依赖的是左下角的值,所以遍历顺序应该是从下往上,从左到右来遍历的
(5)打印dp数组。
class Solution {
public:
int countSubstrings(string s) {
vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));
int result = 0;
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) {dp[i][j] = true; result++;}
else{
if(dp[i+1][j-1] == true){
dp[i][j] = true;
result++;
}
}
}
}
}
return result;
}
};
题目二:516.最长回文子序列
Leetcode题目:【516.最长回文子序列】
与上题的区别就是子序列是不连续,按照动规五部曲进行分析:
(1)定义dp数组dp[i][j]:区间【i,j】的最长回文子序列长度为dp[i][j];
(2)确定递推公式:
if(s[i] == s[j]) dp[i][j] = dp[i+1][j-1] + 2;
else{
dp[i][j] = max(dp[i][j-1], dp[i+1][j]);
}
(3)初始化:(最关键)
当i和j相同的时候,dp[i][j] = 1;
(4)遍历顺序:从左到右,从下到上
(5)打印dp数组。
class Solution {
public:
int longestPalindromeSubseq(string s) {
vector<vector<int>> dp(s.size(), vector<int>(s.size()));
for(int i = 0; i<s.size(); i++){
for(int j = 0; j<s.size(); j++){
if(i==j) dp[i][j] = 1;
}
}
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][j-1], dp[i+1][j]);
}
}
}
return dp[0][s.size()-1];
}
};
三、动态规划总结篇
3.1 动态规划基础
3.2 背包问题
3.3 打家劫舍
3.4 股票系列
3.5 子序列问题