0131. Palindrome Partitioning

https://leetcode.com/problems/palindrome-partitioning

Description

Given a string s, partition s such that every substring of the partition is a palindrome. Return all possible palindrome partitioning of s.

A palindrome string is a string that reads the same backward as forward.

Example 1:

**Input:** s = "aab"
**Output:** [["a","a","b"],["aa","b"]]

Example 2:

**Input:** s = "a"
**Output:** [["a"]]

Constraints:

  • 1 <= s.length <= 16

  • s contains only lowercase English letters.

ac1: Backtracking, DFS

key:

  • isPalindrome();

  • think it as array subset problem

class Solution {
    public List<List<String>> partition(String s) {
        List<List<String>> res = new ArrayList<List<String>>();
        List<String> tmpres = new ArrayList<String>();
        backtrack(s, 0, tmpres, res);
        return res;
    }
    private void backtrack(String s,
                           int start,
                           List<String> tmpres,
                           List<List<String>> res
                          ) {
        if (start > s.length()) return;
        if (start == s.length()) {
            res.add(new ArrayList<String>(tmpres));
            return;
        }

        for (int i = start+1; i <= s.length(); i++) {
            if (!isPalindrome(s.substring(start, i))) continue;
            tmpres.add(s.substring(start, i));
            backtrack(s, i, tmpres, res);
            tmpres.remove(tmpres.size()-1);
        }
    }
    private boolean isPalindrome(String s) {
        for (int i = 0, j = s.length() - 1; i < s.length() && j >= 0; i++, j--) {
            if (s.charAt(i) != s.charAt(j)) return false;
        }
        return true;
    }
}

ac2: improve isPalindrome

https://leetcode.com/problems/palindrome-partitioning/discuss/41982/Java-DP-%2B-DFS-solution

class Solution {
    boolean[][] isPalindrome;

    public List<List<String>> partition(String s) {
        List<List<String>> res = new ArrayList<>();
        // Edge cases
        if (s == null || s.length() == 0) {
            return res;
        }

        init(s);

        process(0, s, new ArrayList<>(), res);

        return res;
    }

    private void process(int start, String s, List<String> note, List<List<String>> res) {
        // Exit
        if (start >= s.length()) {
            res.add(new ArrayList<>(note));
            return;
        }

        for (int i = start; i < s.length(); i++) {
            if (isPalindrome[start][i]) {
                note.add(s.substring(start, i+1));
                process(i+1, s, note, res);
                note.remove(note.size() - 1);
            }
        }
    }

    private void init(String s) {
        isPalindrome = new boolean[s.length()][s.length()];
        for (int i = 0; i < s.length(); i++) {
            for (int j = 0; j <= i; j++) {
                if (s.charAt(i) == s.charAt(j) && (i - j <= 2 || isPalindrome[j+1][i-1])) {
                    isPalindrome[j][i] = true;
                }
            }
        }
    }
}

ac3: faster

  • substring() is O(n) where n is the length of substring.

  • class Solution {
      public List<List<String>> partition(String s) {
          List<List<String>> res = new ArrayList<List<String>>();
          List<String> tmpres = new ArrayList<String>();
          backtrack(s, 0, tmpres, res);
          return res;
      }
      private void backtrack(String s,
                             int start,
                             List<String> tmpres,
                             List<List<String>> res
                            ) {
          int len = s.length();
          if (start >= len) {
              res.add(new ArrayList<String>(tmpres));
              return;
          }
    
          for (int i = start; i < len; i++) {
              if (isPalindrome(s, start, i)){
                  tmpres.add(s.substring(start, i+1));
                  backtrack(s, i+1, tmpres, res);
                  tmpres.remove(tmpres.size()-1);
              }
    
          }
      }
      private boolean isPalindrome(String s, int l, int r) {
          if (l == r) return true;
          while (l < r) {
              if (s.charAt(l) != s.charAt(r)) return false;
              l++;
              r--;
          }
          return true;
      }
    }

ac4: Memorization + DFS

it's slower and even error-prone

class Solution {
    public List<List<String>> partition(String s) {
        Map<Integer, List<List<String>>> map = new HashMap<Integer, List<List<String>>>();
        return dfs(s, 0, map);
    }
    private List<List<String>> dfs(String s, int start, Map<Integer, List<List<String>>> map) {
        List<List<String>> res = new ArrayList<List<String>>();
        int len = s.length();
        if (start == len) {
            res.add(new ArrayList<>());
            return res;
        } 

        // memorization
        if (map.containsKey(start)) return map.get(start);

        // iterate
        for (int i = start + 1; i <= len; i++) {
            if (isPalindrome(s.substring(start, i))) {
                List<List<String>> child = dfs(s, i, map);
                for (List<String> list : child) {
                    List<String> tmp = new ArrayList<String>();
                    tmp.add(s.substring(start, i));
                    tmp.addAll(list);
                    res.add(tmp);
                }
                // res.addAll(child);
            }
        }

        map.put(start, res);
        return res;
    }
    private boolean isPalindrome(String s) {
        int l = 0, r = s.length() - 1;
        while (l < r) {
            if (s.charAt(l) != s.charAt(r)) {
                return false;
            }
            l++;
            r--;
        }
        return true;
    }
}
/*
backtracking
memorization + DFS: 1) not visited, 2) visited + result, 3) visited no result
*/

Last updated