题目

Given a string s, partition s such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of s.

Example:

  1. Input: "aab"
  2. Output:
  3. [
  4. ["aa","b"],
  5. ["a","a","b"]
  6. ]

题意

对给定字符串进行划分,使其分出的每一部分都是一个回文子串。求出所有这样的划分方式。

思路

DFS处理。

可以利用动态规划对判断回文这一步骤进行优化:设若P[i][j]==true,则字符串s中从下标i到下标j构成的子串为回文子串,则很容易得到状态转移方程及边界条件如下:
0131. Palindrome Partitioning (M) - 图1
0131. Palindrome Partitioning (M) - 图2


代码实现

Java

暴力递归

  1. class Solution {
  2. public List<List<String>> partition(String s) {
  3. List<List<String>> ans = new ArrayList<>();
  4. dfs(s, ans, new ArrayList<>());
  5. return ans;
  6. }
  7. private void dfs(String s, List<List<String>> ans, List<String> temp) {
  8. if (s.equals("")) {
  9. ans.add(new ArrayList<>(temp));
  10. return;
  11. }
  12. for (int i = 1; i <= s.length(); i++) {
  13. String sub = s.substring(0, i);
  14. if (isPalindrome(sub)) {
  15. temp.add(sub);
  16. dfs(s.substring(i), ans, temp);
  17. temp.remove(temp.size() - 1);
  18. }
  19. }
  20. }
  21. private boolean isPalindrome(String s) {
  22. int left = 0, right = s.length() - 1;
  23. while (left < right) {
  24. if (s.charAt(left++) != s.charAt(right--)) {
  25. return false;
  26. }
  27. }
  28. return true;
  29. }
  30. }

动态规划优化

  1. class Solution {
  2. public List<List<String>> partition(String s) {
  3. List<List<String>> ans = new ArrayList<>();
  4. boolean[][] dp = new boolean[s.length()][s.length()];
  5. // 生成dp数组
  6. for (int len = 1; len <= s.length(); len++) {
  7. for (int i = 0; i + len - 1 < s.length(); i++) {
  8. int j = i + len - 1;
  9. if (len == 1) {
  10. dp[i][j] = true;
  11. } else if (len == 2) {
  12. dp[i][j] = s.charAt(i) == s.charAt(j);
  13. } else {
  14. dp[i][j] = dp[i + 1][j - 1] && s.charAt(i) == s.charAt(j);
  15. }
  16. }
  17. }
  18. dfs(s, dp, 0, ans, new ArrayList<>());
  19. return ans;
  20. }
  21. private void dfs(String s, boolean[][] dp, int start, List<List<String>> ans, List<String> temp) {
  22. if (start == s.length()) {
  23. ans.add(new ArrayList<>(temp));
  24. return;
  25. }
  26. for (int end = start; end < s.length(); end++) {
  27. if (dp[start][end]) {
  28. temp.add(s.substring(start, end + 1));
  29. dfs(s, dp, end + 1, ans, temp);
  30. temp.remove(temp.size() - 1);
  31. }
  32. }
  33. }
  34. }

JavaScript

  1. /**
  2. * @param {string} s
  3. * @return {string[][]}
  4. */
  5. var partition = function (s) {
  6. let ans = []
  7. let judge = new Array(s.length).fill(0).map(item => new Array(s.length).fill(false))
  8. for (let len = 1; len <= s.length; len++) {
  9. for (let left = 0; left + len - 1 < s.length; left++) {
  10. let right = left + len - 1
  11. if (left === right) {
  12. judge[left][right] = true
  13. } else if (right === left + 1) {
  14. judge[left][right] = s[left] === s[right]
  15. } else {
  16. judge[left][right] = judge[left + 1][right - 1] && s[left] === s[right]
  17. }
  18. }
  19. }
  20. dfs(s, 0, judge, ans, [])
  21. return ans
  22. }
  23. let dfs = function (s, start, judge, ans, tmp) {
  24. if (start === s.length) {
  25. return ans.push([...tmp])
  26. }
  27. for (let end = start; end < s.length; end++) {
  28. if (judge[start][end]) {
  29. tmp.push(s.slice(start, end + 1))
  30. dfs(s, end + 1, judge, ans, tmp)
  31. tmp.pop()
  32. }
  33. }
  34. }