1. 问题分析与算法设计思路
LeetCode 730题"统计不同回文子序列"是一个经典的动态规划问题,要求计算字符串中所有不同的非空回文子序列的数量。这个问题在技术面试中经常出现,因为它很好地考察了候选人对动态规划的理解和应用能力。
1.1 问题重述
给定一个字符串s,我们需要统计其中所有不同的非空回文子序列的数量。回文子序列是指正读反读都相同的子序列,且不同的定义是指内容不同而非位置不同。例如,字符串"bccb"的回文子序列包括:
- 单字符:"b","c","c","b"
- 双字符:"bb","cc","cc","bcb","ccb"
- 四字符:"bccb"
1.2 动态规划解法思路
这道题的标准解法是使用区间动态规划(Interval DP)。我们定义一个二维数组dp[i][j],表示字符串s从i到j的子串中不同回文子序列的数量。关键思路是:
- 对于每个区间[i,j],我们枚举可能的4种字符('a','b','c','d')作为回文子序列的首尾字符
- 如果该字符在区间内不存在,则跳过
- 如果该字符在区间内只出现一次,则只能形成单字符回文
- 如果该字符在区间内出现多次,则可以形成多种回文子序列
1.3 状态转移方程
状态转移的核心逻辑可以表示为:
code复制dp[i][j] = sum_{k=0}^3 (处理字符k的情况)
对于每个字符k:
- 如果在[i,j]区间内找不到k,贡献为0
- 如果只找到一个k,贡献为1(单字符回文)
- 如果找到两个及以上k,贡献为2 + dp[L+1][R-1],其中L是第一个k的位置,R是最后一个k的位置
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 代码实现详解
2.1 基础设置与预处理
java复制private static final int MOD = 1_000_000_007;
public int countPalindromicSubsequences(String s) {
int n = s.length();
int[][] dp = new int[n][n];
// 将字符映射为0-3,减少内存使用
int[] nums = new int[n];
for (int i = 0;
