LeetCode 131. Palindrome Partitioning

问题描述

  • Given a string s, partition s such that every substring of the partition is a palindrome.
    Return all possible palindrome partitioning of s.
  • Example :

Input: “aab”
Output:
[
[“aa”,”b”],
[“a”,”a”,”b”]
]

问题分析

  • 拆分一个给定的字符串,使得拆分后的所有子串都是回文串,返回所有拆分的可能。
  • 这是得到枚举所有可能性类型的题目,所以要用 DFS + 回溯 的方法。对当前决策枚举出所有可能性(可走的路径),然后对每一种可能性进行 DFS。每当走完一种可能性,必须回溯到先前的状态,再走另一种可能性。
  • 但该题还有个知识点便是回文串的判断涉及到动态规划, 比如对于 aabccb,如果我们已经找到 [a, a, bccd]后,再进行[aa,bccd]的查找时,会对 bccd 造成重复的是否回文的判断,所以如果我们利用动态规划找到 [i…j]所有的情况,存入表中,在dfs判断回文的时候,进行查表即可,不必重复判断。

经验教训

  • 若涉及到枚举所有可能性,那么便是 DFS + 回溯
  • 如何利用动态规划,填好 isPalindrome 那张表。

代码实现

class Solution {

    public List<List<String>> partition(String s) {
        if (s == null) {
            return new ArrayList<>();
        }
        char[] chs = s.toCharArray();
        ArrayList<String> list = new ArrayList<>();
        //根据动态规划,填好isPalindrome这个二维表,isPalindrome[i][j] 表示 chs[i~j]是否是回文串
        boolean[][] isPalindrome = setPalindromeMap(chs);
        List<List<String>> res = new ArrayList<>();
        findPalindrome(chs, 0, list, res, isPalindrome);
        return res;
    }

    //[0 ~ i - 1]已经决策完成,形成了list,继续决策 [i ~ length - 1],若到了末尾,则加入结果集中
    public void findPalindrome(char[] chs, int i, ArrayList<String> list, List<List<String>> res, boolean[][] isPalindrome) {
        if (i == chs.length) {
            //添加的是副本
            res.add(new ArrayList<>(list));
        }
        //看从i开始,一直到末尾,当前若能得到回文串,则继续dfs
        for (int k = i; k < chs.length; k++) {
            if (isPalindrome[i][k]) { //chs[i ~ k] 是回文
                list.add(new String(chs, i, k - i + 1)); //计入list
                findPalindrome(chs, k + 1, list, res, isPalindrome); //继续dfs
                //回溯!!!
                list.remove(list.size() - 1);
            }
        }
        return; 
    }

    //根据动态规划,填好isPalindrome这个二维表,isPalindrome[i][j] 表示 chs[i~j]是否是回文串
    public boolean[][] setPalindromeMap(char[] chs) {
        boolean[][] isPalindrome = new boolean[chs.length][chs.length];
        //只填右上半部分即可,dp[i][j] 依赖于 dp[i + 1][j - 1] 
        //若所依赖的dp[i + 1][j - 1] 不在右上半部分(i+1 > j - 1) , 直接返回true
        for (int i = chs.length - 1; i >= 0; i--) {
            isPalindrome[i][i] = true;
            for(int j = i + 1; j < chs.length; j++) {
                if (chs[i] == chs[j]) {
                    isPalindrome[i][j] = i+1 > j - 1 || isPalindrome[i + 1][j - 1];
                }
            }
        }
        return isPalindrome;
    }

    //动态规划初始递归思想
    public boolean isPalindrome(char[] chs, int begin, int end) {
        if (begin >= end) {
            return true;
        }
        if (chs[begin] == chs[end]) {
            return isPalindrome(chs, begin + 1, end - 1);
        }
        return false;

        /*
        while(begin < end) {
            if(chs[begin] != chs[end]) {
                return false;
            }
            ++begin;
            --end;
        }
        return true;
        */
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值