132.Palindrome Partitioning II

题目链接

题目大意:给出一个字符串,对其进行划分,形成所有子串是回文串,找出最小需要划分的次数。比如字符串"aab",最小的划分次数是1,形成"aa","b",都是回文串。

法一:利用131题的DFS,超时。代码如下:

 1     private static int dfs(String s, int res, int start, ArrayList<String> tmp) {
 2         //如果找到一种划分情况,则将其接入结果集中
 3         if(start == s.length()) {
 4             if(tmp.size() - 1 < res) {
 5                 res = tmp.size() - 1;
 6             }
 7             return res;
 8         }
 9         //寻找每一个可能的回文字符串
10         for(int i = start; i < s.length(); i++) {
11             //判断字符串的其中一个子串,如果是回文
12             if(isPalindrome(s, start, i) == true) {
13                 //将这个回文子串加入结果中,记住substring(start,end),是从start到end-1的字符串。
14                 tmp.add(s.substring(start, i + 1));
15                 //注意,下次划分的子串起始点应该是i+1,因为i已经在上一个子串中了
16                 res = dfs(s, res, i + 1, tmp);
17                 //回溯移除
18                 tmp.remove(tmp.size() - 1);
19             }
20         }
21         return res;
22     }
23     //判断回文
24     private static boolean isPalindrome(String s, int start, int end) {
25         while(start <= end) {
26             if(s.charAt(start) != s.charAt(end)) {
27                 return false;
28             }
29             start++;
30             end--;
31         }
32         return true;
33     }
View Code

法二:用到了5题的DP,就是利用DP求解回文子字符串的问题,但是这题还扩展了,不仅求解回文子串,还要求解最小分割数,使得所有子串都是回文串,比如"aab",最后的DP数组就是,dp[0][0],dp[1][1],dp[2][2],这是一次分割;dp[0][1],dp[2][2],这是一次分割。可以看出dp[i][j]就是代表i到j的字符串是否是回文串,然后根据dp数组,再计算分割数。为了节约时间,两者放在一起同时计算,而分割数的dp方程是mi[i] = Math.min(mi[i], mi[j + 1] + 1)。mi[i]表示i到n-1的字符串需要分割的最小次数。代码如下(耗时20ms):

 1     public int minCut(String s) {
 2         //dp[i][j]表示在i到j之间的字符串是否是回文串
 3         boolean[][] dp = new boolean[s.length()][s.length()];
 4         for(int i = 0; i < s.length(); i++) {
 5             dp[i][i] = true;
 6         }
 7         //mi[i]表示i到n-1之间的字符串最小需要分割的次数
 8         //从后往前计算
 9         int[] mi = new int[s.length() + 1];
10         for(int i = s.length() - 1; i >= 0; i--) {
11             mi[i] = Integer.MAX_VALUE;//初始化在i的后面分割一下
12             for(int j = i; j < s.length(); j++) {
13                 if(s.charAt(i) == s.charAt(j) && (j - i <= 1 || dp[i + 1][j - 1] == true)) {
14                     dp[i][j] = true;
15                     //因为i到j构成回文串,所以可以考虑在j后面分割,然后与在i后面分割进行比较
16                     mi[i] = Math.min(mi[i], 1 + mi[j + 1]);
17                 }
18             }
19         }
20         return mi[0] - 1;
21     }
View Code

 

posted on 2018-04-11 15:38  二十年后20  阅读(111)  评论(0编辑  收藏  举报

导航