LeetCode hot 100—分割回文串

题目

给你一个字符串 s,请你将 s 分割成一些 子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。

示例

示例 1:

输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]

示例 2:

输入:s = "a"
输出:[["a"]]

分析

要将字符串 s 分割成一些子串,使得每个子串都是回文串,并返回所有可能的分割方案,可以使用回溯算法来解决这个问题。回溯算法通过递归的方式尝试所有可能的分割方案,同时利用动态规划来预先判断子串是否为回文串,以减少重复计算。

回溯+动态规划

代码解释

partition 函数

首先初始化 isPalindrome 数组。使用动态规划计算所有子串是否为回文串。对于长度为 1 或 2 的子串,直接判断首尾字符是否相等;对于长度大于 2 的子串,需要同时满足首尾字符相等且中间子串也是回文串。

调用 backtrack 函数开始生成分割方案。返回所有可能的分割方案。

backtrack 函数

该函数是回溯算法的核心,用于生成所有可能的分割方案。

如果 start 等于字符串的长度,说明已经遍历完字符串,将当前分割方案加入结果集。

遍历从 start 到字符串末尾的所有可能的子串,如果该子串是回文串,将其加入当前分割方案,然后递归调用 backtrack 函数处理剩余的字符串,最后回溯,撤销选择。

时间复杂度:O(n\times 2^{n}), n 是字符串的长度,最坏情况下字符串的每个位置都可以作为分割点,因此有 2^{n-1} 种分割方案,对于每种方案,需要 O(n) 的时间来判断子串是否为回文串。

空间复杂度:O(n^{2})

class Solution {
private:
    // 存储所有可能的分割方案
    std::vector> result;
    // 存储当前的分割方案
    std::vector current;
    // 二维数组,用于存储子串是否为回文串的信息
    std::vector> isPalindrome;

    // 回溯函数,用于生成所有可能的分割方案
    void backtrack(const std::string& s, int start) {
        if (start == s.length()) {
            // 如果已经遍历完字符串,将当前分割方案加入结果集
            result.push_back(current);
            return;
        }
        for (int end = start; end < s.length(); ++end) {
            if (isPalindrome[start][end]) {
                // 如果当前子串是回文串,将其加入当前分割方案
                current.push_back(s.substr(start, end - start + 1));
                // 递归调用回溯函数,继续处理剩余的字符串
                backtrack(s, end + 1);
                // 回溯,撤销选择
                current.pop_back();
            }
        }
    }

public:
    std::vector> partition(std::string s) {
        int n = s.length();
        // 初始化 isPalindrome 数组
        isPalindrome.resize(n, std::vector(n, false));
        // 动态规划计算所有子串是否为回文串
        for (int len = 1; len <= n; ++len) {
            for (int i = 0; i <= n - len; ++i) {
                int j = i + len - 1;
                if (s[i] == s[j]) {
                    if (len <= 2 || isPalindrome[i + 1][j - 1]) {
                        isPalindrome[i][j] = true;
                    }
                }
            }
        }
        // 调用回溯函数开始生成分割方案
        backtrack(s, 0);
        return result;
    }
};    

你可能感兴趣的:(leetcode,leetcode,算法,职场和发展,数据结构,c++)