力扣———1745.分割回文串IV

发布于:2025-03-06 ⋅ 阅读:(32) ⋅ 点赞:(0)

题目要求判断一个字符串是否可以分割成三个非空回文子串。

题目描述
给定一个字符串 `s`,判断是否可以将 `s` 分割成三个非空子串 `s1`, `s2`, `s3`,使得 `s1`, `s2`, `s3` 都是回文串。如果是,返回 `true`;否则,返回 `false`。

解决思路
1. 回文判断:首先需要判断一个子串是否是回文串。可以通过动态规划预处理,记录所有子串是否是回文。
2. 分割点枚举:遍历所有可能的分割点,检查是否可以分成三个回文子串。

动态规划预处理
1. 定义 `dp[i][j]` 表示字符串 `s` 从第 `i` 个字符到第 `j` 个字符是否是回文串。
2. 状态转移方程:
   - 如果 `s[i] == s[j]`,则 `dp[i][j] = dp[i+1][j-1]`。
   - 如果 `i == j`,则 `dp[i][j] = true`。
   - 如果 `j = i + 1`,则 `dp[i][j] = (s[i] == s[j])`。

代码实现

#include <vector>
#include <string>

using namespace std;

class Solution {
public:
    bool checkPartitioning(string s) {
        int n = s.size();
        // 预处理 dp 数组
        vector<vector<bool>> dp(n, vector<bool>(n, false));
        for (int i = n - 1; i >= 0; --i) {
            for (int j = i; j < n; ++j) {
                if (s[i] == s[j]) {
                    if (j - i <= 1) {
                        dp[i][j] = true;
                    } else {
                        dp[i][j] = dp[i + 1][j - 1];
                    }
                }
            }
        }

        // 枚举分割点
        for (int i = 1; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                if (dp[0][i - 1] && dp[i][j - 1] && dp[j][n - 1]) {
                    return true;
                }
            }
        }

        return false;
    }
};
 

 复杂度分析
1. 时间复杂度:O(n^2),其中 `n` 是字符串的长度。预处理 `dp` 数组需要 O(n^2),枚举分割点需要 O(n^2)。
2. 空间复杂度:O(n^2),用于存储 `dp` 数组。

边界情况
1. 字符串长度小于 3:无法分割成三个非空子串,直接返回 `false`。
2. 整个字符串是回文:可以分割成三个相同的子串。
3. 无法找到合适的分割点:返回 `false`。

总结
通过动态规划预处理回文子串信息,再枚举所有可能的分割点,可以高效地解决这个问题。时间复杂度为 _O(n^2)_,适用于中等长度的字符串。


网站公告

今日签到

点亮在社区的每一天
去签到