647. 回文子串
https://programmercarl.com/0647.%E5%9B%9E%E6%96%87%E5%AD%90%E4%B8%B2.html
思路
int countSubstrings(char* s) {
int n = strlen(s);
int count = 0;
for (int center = 0; center < 2 * n - 1; center++) {
int left = center / 2;
int right = left + (center % 2);
while (left >= 0 && right < n && s[left] == s[right]) {
count++;
left--;
right++;
}
}
return count;
}
学习反思
用来计算回文子串的数量。算法的核心思想是以每个字符为中心,向左右两边扩展,统计回文子串的数量。具体实现如下:
- 定义一个变量n来记录字符串s的长度。
- 定义一个变量count来记录回文子串的数量,初始值为0。
- 使用一个循环,遍历字符串s的所有可能的中心点(center)。中心点的范围是从0到2 * n - 1,其中n为字符串s的长度。
- 根据中心点的位置,计算出回文子串的左边界(left)和右边界(right)。左边界是center除以2的整数部分,右边界是左边界加上(center % 2)。这样可以处理字符串长度为奇数和偶数的情况。
- 使用一个循环,从左右边界开始向两边扩展,判断左右边界对应的字符是否相等。如果相等,说明找到了一个回文子串,count加1,并且左边界向左移动一位,右边界向右移动一位。
- 继续扩展直到左边界小于0或者右边界大于等于n,即越界情况。这时候就停止扩展,跳出内层循环。
- 返回回文子串的数量count。
这个算法的时间复杂度是O(n^2)。
516.最长回文子序列
https://programmercarl.com/0516.%E6%9C%80%E9%95%BF%E5%9B%9E%E6%96%87%E5%AD%90%E5%BA%8F%E5%88%97.html
思路
int longestPalindromeSubseq(char* s) {
int n = strlen(s);
int dp[n][n];
memset(dp, 0, sizeof(dp));
for (int i = n - 1; i >= 0; i--) {
dp[i][i] = 1;
char c1 = s[i];
for (int j = i + 1; j < n; j++) {
char c2 = s[j];
if (c1 == c2) {
dp[i][j] = dp[i + 1][j - 1] + 2;
} else {
dp[i][j] = fmax(dp[i + 1][j], dp[i][j - 1]);
}
}
}
return dp[0][n - 1];
}
学习反思
实现了找到字符串s的最长回文子序列的长度。下面是对代码的学习反思:
-
代码使用动态规划来解决问题。使用一个二维数组dp来存储已经计算过的子问题的解。dp[i][j]表示s[i]到s[j]之间的子序列的最长回文子序列的长度。
-
首先初始化dp数组,将所有元素都置为0。
-
使用两个嵌套的循环,从后往前遍历字符串s。外层循环遍历每个起始位置i,内层循环遍历每个结束位置j。
-
在每个位置i和j处,判断s[i]和s[j]是否相等。如果相等,则说明s[i]和s[j]可以扩展回文子序列的长度,即dp[i][j] = dp[i + 1][j - 1] + 2。
-
如果s[i]和s[j]不相等,则说明s[i]和s[j]不能同时出现在最长回文子序列中,需要选择其中一个进行扩展。选择dp[i + 1][j]和dp[i][j - 1]中较大的一个作为dp[i][j]的值。
-
最终返回dp[0][n - 1],即整个字符串s的最长回文子序列的长度。
这段代码的时间复杂度为O(n^2)。
总结
加油!!!