这个题目还可以,主要是对首尾相同字符的搜索,以及两相同字符间不同字符的数目的处理。
用的力扣官方解法,简单易懂
cpp
class Solution {
public:
int countPalindromicSubsequence(string s) {
int n = s.size(); // 存储字符串s的长度
int res = 0; // 存储最终的会问子序列数量
// 枚举所有可能的首尾字符
for (char ch = 'a'; ch <= 'z'; ++ch) { // 从a-z,++表示变成下一个字母
int l = 0, r = n - 1; // 定义字符串起始索引left 末尾索引right
// 寻找该字符第一次出现的下标
while (l < n && s[l] != ch) {
l++;
}
// 寻找该字符最后一次出现的下标
while (r >= 0 && s[r] != ch) {
--r;
}
// 如果 r - l < 2,意味着 l 和 r
// 指向同一个位置(r-l=0),或者它们是相邻的(r-l=1),都没有足够的空间容纳一个中间字符,因此无法构成长度为
// 3 的回文子序列 。
if (r - l < 2) {
// 该字符未出现,或两下标中间的子串不存在
continue;
}
// 定义一个 unordered_set(无序哈希集合),用于存储在 l 和 r
// 之间发现的所有不同字符。unordered_set 的特性是自动去重
// 利用哈希集合统计s[l+1..r-1]子串的字符总数,并更新答案
unordered_set<char> charset;
// 循环遍历 l 和 r 之间的所有字符(不包括 l 和 r 本身)。
for (int k = l + 1; k < r; ++k) {
// 当前遍历到的字符 s[k] 插入到哈希集合 charset 中。如果 s[k]
// 已经存在于集合中,insert 操作不会做任何事情。
charset.insert(s[k]);
}
// 环结束后,charset 中存储的就是 l 和 r
// 之间所有不重复的中间字符。集合的大小(charset.size())就是以当前
// ch 为首尾的不同回文子序列的数量。将这个数量加到最终结果 res 上。
res += charset.size();
}
return res;
}
};
代码的核心思路是**利用回文子序列 "首尾字符相同、中间字符任意" 的特点,通过枚举首尾字符 + 统计中间字符种类来计算不同回文子序列的数量,**逐部分解释:
一、题目核心要求
需要统计长度为 3 的不同回文子序列 的个数。长度为 3 的回文子序列的结构是 aba(首尾字符相同,中间字符任意),且相同的子序列只计数一次。
二、代码逻辑拆解
1. 枚举所有可能的 "首尾字符"
长度为 3 的回文子序列,首尾字符必须相同(记为 ch)。代码中通过 for (char ch = 'a'; ch <= 'z'; ++ch) 枚举 26 个小写字母作为首尾字符。
2. 找到首尾字符的 "第一次" 和 "最后一次" 出现位置
l:字符ch在字符串s中第一次出现的下标 (通过while (l < n && s[l] != ch)从左向右找);r:字符ch在字符串s中最后一次出现的下标 (通过while (r >= 0 && s[r] != ch)从右向左找)。
若 r - l < 2(即 l 和 r 之间没有至少 1 个字符),说明无法构成 "首尾为 ch、长度为 3" 的子序列,直接跳过当前字符。
3. 统计 "首尾之间" 的所有不同字符(中间字符)
首尾字符确定为 ch 后,中间字符可以是 s[l+1..r-1] 中的任意字符,且每个不同的中间字符对应一个不同的回文子序列 (如首尾是 a,中间是 b 对应 aba,中间是 c 对应 aca)。
代码中用 unordered_set<char> charset 统计 s[l+1..r-1] 中的所有不同字符(set 自动去重),charset.size() 就是当前首尾字符 ch 对应的不同回文子序列数量,将其累加到结果 res 中。
三、示例验证(以示例 1 s = "aabca" 为例)
- 枚举
ch = 'a':l = 0(第一个a),r = 4(最后一个a);- 中间字符是
s[1..3] = "abc",charset包含a、b、c,大小为 3; res += 3(此时res = 3)。
- 枚举其他字符(如
b):l = 2(第一个b),r = 2(最后一个b),r - l < 2,跳过。
- 最终
res = 3,与示例 1 的输出一致。
四、总结
这个代码的核心是 利用 "首尾字符相同 + 中间字符去重"的策略,通过枚举 26 个字母的首尾位置,结合哈希集合统计中间字符的种类,高效计算出所有不同的长度为 3 的回文子序列,时间复杂度为 O (26*n)(n 是字符串长度)。