題目:
Palindrome Partitioning
I
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
For example, given s = "aab",
Return
[ ["aa","b"], ["a","a","b"] ]
分析:
題意給我們一個字串,求出所有這個字串的子串,並且子串都為迴文字串的情況,輸出它的集合結果
解題思路:(跟DFS深度遍曆有點像!)
字串Str = "aab";
分析了題目的資料之後,我們知道它的結果,可能是 a, a, b 或者 aa, b 這樣的情況!
也就是說,我們需要去考慮 i = 1, 2 .... n 的情況,比如
Str = "aaa"
結果集
[[a, a, a], [a, aa], [aa, a], [aaa]]
根據這樣的情況,我們用類似於DFS的演算法
str1 = str.substr(0, i); 取出前面下標從 0 開始到 i 結束的子串,判斷str1是否滿足迴文字串的要求,
1. 滿足:這樣子,有可能成為一種分割的情況,所以我們new出一個list集合,把str1放入到list中,然後我們求出str剩餘的子串 str2 = str.substr(i); 取出前面下標從 i 開始到整個字串結尾的子串, 然後將str2 作為新的字串,同時把list集合也傳入到函數中,遞迴調用。遞迴的結束條件就是到傳入的這個字串的長度為0(這樣就意味著已經到了字串的末尾了),此時證明這種情況下得到的list集合是滿足條件的,我們把這個list集合 加入到 結果集合result中。
2. 不滿足的話,繼續 i++, 直到 i == str.length();
3. 全部結束之後,返回 最終的結果集合 result
AC代碼:
package copylist;import java.util.ArrayList;public class Solution {/* * 供外部調用 * */ public ArrayList<ArrayList<String>> partition(String s) { ArrayList<ArrayList<String>> result = new ArrayList<ArrayList<String>>(); ArrayList<String> list = new ArrayList<String>(); if (s == null || s.length() == 0) return result; calResult(result,list,s); return result; } /** * 判斷一個字串是否是迴文字串 * i -> str[0] * j -> str[len-1] * i:往後移 * j:往前移 * @param str * @return */ private boolean isPalindrome(String str){ int i = 0; int j = str.length() - 1; while (i < j){ if (str.charAt(i) != str.charAt(j)){ return false; } i++; j--; } return true; } /** * * @param result : 最終要的結果集 ArrayList<ArrayList<String>> * @param list : 當前已經加入的集合 ArrayList<String> * @param str : 當前要處理的字串 */ private void calResult(ArrayList<ArrayList<String>> result , ArrayList<String> list , String str) { //當處理到傳入的字串長度等於0,則這個集合list滿足條件,加入到結果集中 if (str.length() == 0) result.add(new ArrayList<String>(list)); int len = str.length(); //遞迴調用 //字串由前往後,先判斷str.substring(0, i)是否是迴文字串 //如果是的話,繼續調用函數calResult,把str.substring(i)字串傳入做處理 for (int i=1; i<=len; ++i){ String subStr = str.substring(0, i); if (isPalindrome(subStr)){ list.add(subStr); String restSubStr = str.substring(i); calResult(result,list,restSubStr); list.remove(list.size()-1); } } } public static void main(String[] args) { System.out.println(new Solution().partition("aabaa")); }}
題目:(DP)
Palindrome Partitioning II
Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
For example, given s = "aab",
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut.
分析:
求出要讓一個字串滿足得到的子串集合都為迴文字串的最小切割數
(跟上一題有一點關係,上一題網上有位牛人用的方法是DP做的,但上一題我們沒有用那種方法,但是這題要用DP哈,不然會TLE哦)
解題思路:
我們可以把這個問題轉換成動態規劃dp的問題
首先我們先定義幾個變數,並對這幾個量做一定的說明!為了方便理解,下面這些為偽碼!!!
len = str.length(); // 字串的長度
int[] cuts = new int[len + 1]; //cuts數組,cuts[i] 表示 以 i 開頭到len結尾的子串 要達到題意需要的最少切割數(這樣子最終 cuts[0]就是我們要的結果)【初始化 cuts[i] = len - i, 因為最壞情況以 i 開頭到len結尾的子串要切割數就是每個字元都切一次】
int[][] matrix = new int[len][len]; //設定出一個鄰接矩陣數組,它所表示的意思:如matrix[i][j] = true, 表示 子串 sub(i, j) 是滿足迴文字串條件的!
那麼判斷matrix[i][j] 是否滿足迴文字串的條件是:
matrix[i+1][j-1] == true (表示sub(i+1,j-1)是滿足迴文字串) && str[i] == str[j]
或者
j - i < 2 && str[i] == str[j] (即如果j - i == 1時,為兩個字元相等,如果j - i == 0時,為同一個字元)
這兩種情況,我們都將matrix[i][j]設定成true,方便下一次的DP,並且我們可以求出最小的切割次數
cuts[i] = min{cuts[i], cuts[j+1] + 1}; 狀態轉移方程式
這樣最後cuts[0] - 1便為 字串str的最小的切割數!!!!
public class test {public int minCut(String s) {int min = 0;int len = s.length();boolean[][] matrix = new boolean[len][len];int cuts[] = new int[len+1];if (s == null || s.length() == 0)return min;//初始化cuts裡面的值為最壞情況的值for (int i=0; i<len; ++i){cuts[i] = len - i;}//dp過程for (int i=len-1; i>=0; --i){for (int j=i; j<len; ++j){if ((s.charAt(i) == s.charAt(j) && (j-i<2))|| (s.charAt(i) == s.charAt(j) && matrix[i+1][j-1])){matrix[i][j] = true;cuts[i] = getMinValue(cuts[i], cuts[j+1]+1);}}}min = cuts[0];return min-1;} public int getMinValue(int a, int b){ return a > b ? b : a; } public static void main(String[] args) { System.out.println(new test().minCut("ababbbabbaba")); }}