碎碎念:
参考:代码随想录
647. 回文子串
题目链接
思想
动态规划五部曲:
- 确定dp数组以及下标的含义:dp[i][j]为true表示[i,j]子串是回文串。
- 确定递推公式:
- dp数组的初始化:都初始化为false
- 确定遍历顺序:两层for循环,从左往右,从下往上遍历
- 打印dp数组:主要用来debug。
用一个result记录回文串个数,最后返回即可。
题解
// cpp
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) {
result ++;
dp[i][j] = true;
} else if (dp[i + 1][j - 1]) {
result ++;
dp[i][j] = true;
}
}
}
}
return result;
}
};
# python
class Solution:
def countSubstrings(self, s: str) -> int:
dp = [[False] * len(s) for _ in range(len(s))]
result = 0
for i in range(len(s) - 1, -1, -1):
for j in range(i, len(s)):
if s[i] == s[j]:
if j - i <= 1:
result += 1
dp[i][j] = True
elif dp[i + 1][j - 1]:
result += 1
dp[i][j] = True
else:
continue
return result
反思
注意本题的遍历顺序。
516.最长回文子序列
题目链接
思想
上一题强调元素连续,本题求的是子序列,不要求连续。
动态规划五部曲:
- 确定dp数组以及下标的含义:[i,j]范围内的回文子序列长度为dp[i][j],最后结果在dp[0][s.size()-1]
- 确定递推公式:如果s[i]==s[j],dp[i][j]=dp[i+1][j-1]+2; 不相等的话,dp[i][j]=max(dp[i][j-1],dp[i+1][j])
- dp数组的初始化:dp[i][i]=1
- 确定遍历顺序:两层for循环,从左往右,从下往上遍历。
- 打印dp数组:主要用来debug。
题解
// cpp
class Solution {
public:
int longestPalindromeSubseq(string s) {
vector<vector<int>> dp(s.size(), vector<int>(s.size(), false));
for (int i = 0; i < s.size(); i++) dp[i][i] = 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 + 1][j], dp[i][j - 1]);
}
}
}
return dp[0][s.size() - 1];
}
};
# python
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
dp = [[0] * len(s) for _ in range(len(s))]
for i in range(len(s)):
dp[i][i] = 1
for i in range(len(s) - 1, -1, -1):
for j in range(i + 1, len(s)):
if s[j] == s[i]:
dp[i][j] = dp[i + 1][j - 1] + 2
else:
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
return dp[0][-1]
反思
注意积累这种题的dp数组含义。