Leetcode - 131. 分割回文串

解题思路参考代码中的注释:
class Solution {

    // 首先,找到字符串s中所有是回文的子串,然后使用回溯法进行回文切分
    public List<List<String>> partition(String s) {
        int length = s.length();
        char[] arr = s.toCharArray();
        List<List<String>> ret = new ArrayList<>();

        // dp[l][r]表示字符串s的[l, r]区间上的子串是否为回文
        // 注意dp[l][r]的动态转移方程中包含dp[l + 1][r - 1]
        // 因此需要保证在判断dp[l][r]时dp[l + 1][r - 1]已经被置为正确的值
        boolean[][] dp = new boolean[length][length];

        for (int r = 0; r < length; r++) {
            
            // 长度为1的字符串一定是回文
            dp[r][r] = true;
            
            for (int l = r - 1; l >= 0; l--) {

                // 如果l和r指向的字符不同,则当前子串肯定不是回文
                // 如果l和r指向的字符相同,则r - l <= 2时当前子串是回文
                // 如果l和r指向的字符相同,且r - l > 2,那么dp[l][r]取决于dp[l + 1][r - 1]
                dp[l][r] = arr[l] != arr[r] ? false : (r - l <= 2 ? true : dp[l + 1][r - 1]);
            }
        }

        // 使用回溯法
        search(s, 0, dp, new LinkedList<>(), ret);
        return ret;
    }

    // 回溯法,该方法的主要作用是从字符串s的下标begin开始找到一个回文,将它放入split集合中
    private void search(String s, int begin, boolean[][] dp, LinkedList<String> split, List<List<String>> ret) {
        int length = s.length();

        // 如果开始的下标正好为字符串的长度,说明找到了一个可行的分割方案
        if (begin == length) {
            ret.add(new ArrayList(split));
            return;
        }

        // 否则,从begin开始寻找回文,将该回文放入split集合中
        for (int i = begin; i < length; i++){
            
            // 不是回文,则跳过
            if (!dp[begin][i]) {
                continue;
            }
            
            // 将回文添加到split集合中
            split.addLast(s.substring(begin, i + 1));
            
            // 继续往下搜索
            search(s, i + 1, dp, split, ret);
            
            // 回溯
            split.pollLast();
        }
    }
}
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务