題目連接數組
題目大意:給出一個字符串,對其進行劃分,造成全部子串是迴文串,找出最小須要劃分的次數。好比字符串"aab",最小的劃分次數是1,造成"aa","b",都是迴文串。ide
法一:利用131題的DFS,超時。代碼以下:spa
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 }
法二:用到了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):3d
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 }