zoukankan      html  css  js  c++  java
  • [LintCode] Palindrome Partitioning II

    Given a string s, cut s into some substrings such that every substring is a palindrome.

    Return the minimum cuts needed for a palindrome partitioning of s.

    Example

    Given s = "aab",

    Return 1 since the palindrome partitioning ["aa", "b"] could be produced using 1 cut.

    Solution 1. Recursion and backtracking

    A straightforward solution is to check all valid partitions and get the minimum cut.

    1. First fix a substring and check if palindromic, if it is, add this substring to a list and 

    recursively partition the rest of the string.

    2. After the entire string is partitioned, update the min cut if necessary.

    3. Backtrack to check other valid partitions. 

    Efficiency: This algorithm is very inefficient for the following two reasons.

    1. The same subproblem is computed redundantly. 

      The following recursion tree shows this.

                "aabbc"

         "abbc"              "bbc"            

       "bbc" 

     2.  Substring palindrome check does not use smaller substring's check result.

           For string "abcd",  if we've checked "bc" is not palindromic, then for sure 

      "abcd" is not palindromic. isPalindorme() does the O(n) check for all substrings,

      not using previous check results. 

     1 public class Solution {
     2     public int minCut(String s) {
     3         if(s == null || s.length() == 0)
     4         {
     5             return -1;
     6         }
     7         ArrayList<Integer> minCut = new ArrayList<Integer>(1);
     8         minCut.add(s.length() - 1);
     9         
    10         minCutHelper(minCut, new ArrayList<String>(), s, 0);
    11 
    12         return minCut.get(0);
    13     }
    14     
    15     private void minCutHelper(ArrayList<Integer> currMinCut, 
    16                               List<String> curr,
    17                               String s, 
    18                               int startIdx)
    19     {
    20         if(curr.size() > 0 && startIdx >= s.length())
    21         {
    22             if((curr.size() - 1) < currMinCut.get(0))
    23             {
    24                 currMinCut.set(0, curr.size() - 1);
    25             }
    26             return;
    27         }
    28         
    29         for(int i = startIdx; i < s.length(); i++)
    30         {
    31             if(isPalindrome(s, startIdx, i))
    32             {
    33                 curr.add(s.substring(startIdx, i + 1));
    34                 minCutHelper(currMinCut, curr, s, i + 1);
    35                 curr.remove(curr.size() - 1);
    36             }
    37         }
    38     }
    39     
    40     private boolean isPalindrome(String str, int left, int right)
    41     {
    42         while(left <= right)
    43         {
    44             if(str.charAt(left) != str.charAt(right))
    45             {
    46                 return false;
    47             }
    48             left++;
    49             right--;
    50         }
    51         return true;
    52     }
    53 }

    Solution 2. Dynamic Programming

    To address the two performance issues in solution 1, we make some time-space tradeoff.

    State:

    pal[i][j] stores if s[i....j] is palindromic or not. 

    minCuts[i] stores the minimal cuts needed to partition substring s[0....i].

    Initialization:

    pa[i][i] = true, as one character is palindromic.

    pa[i][i + 1] = s.charAt(i) == s.charAt(i + 1).

    minCuts[i] = i, as the most cuts for a string of length i + 1 is i. 

    Function:

    pal[i][j] = pal[i + 1][j - 1] && s.charAt(i) == s.charAt(j);  compute the result of shorter length substrings first, as they will be used to compute longer substrings' result.

    For a given substring s[0...j], we check all possible partitions.

    If pal[i][j] == true, s[i....j] is a valid palindromic partition, then the problem of s[0...j] can be reduced to s[0... i - 1] + 1, 1 represents the partition of s[i][j].

      a.  if i == 0, if s[0...j] is palindromic, then no cut is needed for s[0...j].

            minCuts[j] = 0;

      b.  if i > 0, 

         minCuts[j] = Math.min(minCuts[j], minCuts[i - 1] + 1), i is from 1 to j;

     1 public class Solution {
     2     public int minCut(String s) {
     3         if(s == null || s.length() <= 1){
     4             return 0;
     5         }    
     6         int len = s.length();
     7         int[] minCuts = new int[len];
     8         boolean[][] pal = new boolean[len][len];
     9         for (int i = 0; i < len; i++) {
    10             pal[i][i] = true;
    11         }
    12         for (int i = 0; i < len - 1; i++) {
    13             pal[i][i + 1] = (s.charAt(i) == s.charAt(i + 1));
    14         }
    15         for(int i = 0; i < len; i++){
    16             minCuts[i] = i;
    17         }
    18         for (int i = len - 3; i >= 0; i--) {
    19             for (int j = i + 2; j < len; j++) {
    20                 pal[i][j] = pal[i + 1][j - 1] && s.charAt(i) == s.charAt(j);
    21             }
    22         }
    23         for(int i = 0; i < len; i++){
    24             for(int j = 0; j <= i; j++){
    25                 if(pal[j][i]){
    26                     if(j == 0){
    27                         minCuts[i] = 0;
    28                     }
    29                     else{
    30                         minCuts[i] = Math.min(minCuts[i], minCuts[j - 1] + 1);
    31                     }
    32                 }
    33             }
    34         }
    35         return minCuts[len - 1];
    36     }
    37 }

    The above dp uses a 1D array minCuts[i] to store min cut of substring s[0....i].  

    This is similar with Text Justification and Word Break.

    Text Justification:  minCost[i] = min { minCost[j] + cost[j + 1][i] }

    Word Break:  dp[i] = dp[i - lastWordLen] && dict.contains(s.substring(i - lastWordLen, i));  

          dp[i]: if s[0....... i - 1] can be broken into words in dict.

    Related Problems 

    Wiggle Sort II

    Palindrome Partitioning 

    Longest Palindromic Substring

  • 相关阅读:
    Vue 子组件接收父组件的值
    Vue 子组件调用父组件的方法
    dedecms大量删除文章后,列表页显示错误修复办法
    怎么才能快速的删除指定栏目、指定日期、指定id之间的织梦文章内容?
    怎么才能快速的彻底删除织梦文章内容?
    织梦删除专题,删除文章时出现错误inc_batchup.php on line 17 如何解决?
    windows环境下更改Mysql数据库存储位置的具体步骤
    JsonP原理
    建一个别人打不开的文件夹
    Dos环境变量修改
  • 原文地址:https://www.cnblogs.com/lz87/p/7432883.html
Copyright © 2011-2022 走看看