leetcode-分割回文串

119 阅读2分钟

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。

感觉2022来的挺快的,2021有很多想做的事情还没完成。算法也学的断断续续,希望2022可以把上一年未完成的任务都补上。

题目

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

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

示例 2:
输入: s = "a"
输出: [["a"]]

思路

因为要找到所有分割方案,所以这里大方向上应该是回溯。从下标0开始遍历,找到回文串后(假设当前回文串字符开始和下标分别为i、j)加入列表,然后继续从j+1往后遍历和回溯。因为单子字符一定是回文,所以不用担心某一种切割后,后面的字符串无法切换成n个回文串的情况,因为至少可以有一种方案是,把后面的字符串都切成单个字符,一定是一种满足条件的解。
这样,问题就转换成了,如何快速判断s[i][j]是否是一个回文串。
类似的问题应该见过很多了,常见的解法就是打表,把重复计算的中间结果缓存起来,用空间换时间,也是动态规划算法比较重要的思想吧。
我们定义一个布尔类型的2维数组f[i][j],表示s[i][j]是否是一个回文串。因为j一定大于等于i,所以我们只要给一半赋值就行,另外一半是没有意义的。我们可以先把f[0][0]、f[1][1]...f[len-1][len-1]这条对角线值初始化成true,因为单字符一定是回文串,接下来我们分2种情况

  • j = i+1 : f[i][j] = s.charAt(i) == s.charAt(j)
  • j > i+1 : f[i][j] = s.charAt(i) == s.charAt(j) && f[i+1][j-1] 可以看到s.charAt(i) == s.charAt(j)这一步判断是公共的,我们可以提取出来。另外一边,由于f[i][j]依赖于f[i+1][j-1],所以,我们在给f[i][j]赋值是,i这层的循环到从大到小,这样保证在计算f[i][j]的时候,f[i+1][j-1]已经有值了。

Java版本代码

class Solution {
    public List<List<String>> partition(String s) {
        int len = s.length();
        boolean[][] f = new boolean[len][len];
        for (int i = 0; i < len; i++) {
            f[i][i] = true;
        }
        for (int i = len-1; i >= 0; i--) {
            for (int j = i+1; j < len; j++) {
                f[i][j] = s.charAt(i) == s.charAt(j);
                if (f[i][j] && j > i+1) {
                    f[i][j] = f[i+1][j-1];
                }
            }
        }
        List<List<String>> ans = new ArrayList<>();
        List<String> temp = new ArrayList<>();
        dfs131(f, s, len, 0, ans, temp);
        return ans;
    }

    private static void dfs131(boolean[][] f, String s, int len, int index, List<List<String>> ans, List<String> temp) {
        if (index == len) {
            ans.add(new ArrayList<>(temp));
            return;
        }
        for (int i = index; i < len; i++) {
            if (f[index][i]) {
                temp.add(s.substring(index, i + 1));
                dfs131(f, s, len, i + 1, ans, temp);
                temp.remove(temp.size() - 1);
            }
        }
    }

}