题目
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处理。
可以利用动态规划对判断回文这一步骤进行优化:设若P[i][j]==true,则字符串s中从下标i到下标j构成的子串为回文子串,则很容易得到状态转移方程及边界条件如下:
\[P[i][j] = (P[i+1][j-1] \ \&\&\ s[i] == s[j]) \]
\[P[i][j] = \begin{cases} true, &i==j\\ true, &j==i+1 \ \&\&\ s[i]==s[j]\\ false, &j==i+1 \ \&\&\ s[i]\ !=s[j] \end{cases} \]
代码实现
Java
暴力递归
class Solution { public List<List> partition(String s) { List<List> ans = new ArrayList<>(); dfs(s, ans, new ArrayList<>()); return ans; } private void dfs(String s, List<List> ans, Listtemp) { if (s.equals("")) { ans.add(new ArrayList<>(temp)); return; } for (int i = 1; i <= s.length(); i++) { String sub = s.substring(0, i); if (isPalindrome(sub)) { temp.add(sub); dfs(s.substring(i), ans, temp); temp.remove(temp.size() - 1); } } } private boolean isPalindrome(String s) { int left = 0, right = s.length() - 1; while (left < right) { if (s.charAt(left++) != s.charAt(right--)) { return false; } } return true; } }
动态规划优化
class Solution { public List<List> partition(String s) { List<List> ans = new ArrayList<>(); boolean[][] dp = new boolean[s.length()][s.length()]; // 生成dp数组 for (int len = 1; len <= s.length(); len++) { for (int i = 0; i + len - 1 < s.length(); i++) { int j = i + len - 1; if (len == 1) { dp[i][j] = true; } else if (len == 2) { dp[i][j] = s.charAt(i) == s.charAt(j); } else { dp[i][j] = dp[i + 1][j - 1] && s.charAt(i) == s.charAt(j); } } } dfs(s, dp, 0, ans, new ArrayList<>()); return ans; } private void dfs(String s, boolean[][] dp, int start, List<List> ans, Listtemp) { if (start == s.length()) { ans.add(new ArrayList<>(temp)); return; } for (int end = start; end < s.length(); end++) { if (dp[start][end]) { temp.add(s.substring(start, end + 1)); dfs(s, dp, end + 1, ans, temp); temp.remove(temp.size() - 1); } } } }
JavaScript
/** * @param {string} s * @return {string[][]} */ var partition = function (s) { let ans = [] let judge = new Array(s.length).fill(0).map(item => new Array(s.length).fill(false)) for (let len = 1; len <= s.length; len++) { for (let left = 0; left + len - 1 < s.length; left++) { let right = left + len - 1 if (left === right) { judge[left][right] = true } else if (right === left + 1) { judge[left][right] = s[left] === s[right] } else { judge[left][right] = judge[left + 1][right - 1] && s[left] === s[right] } } } dfs(s, 0, judge, ans, []) return ans } let dfs = function (s, start, judge, ans, tmp) { if (start === s.length) { return ans.push([...tmp]) } for (let end = start; end < s.length; end++) { if (judge[start][end]) { tmp.push(s.slice(start, end + 1)) dfs(s, end + 1, judge, ans, tmp) tmp.pop() } } }