Palindrome Partitioning II

来源:互联网 发布:ipad软件的目录 编辑:程序博客网 时间:2024/05/16 08:58

题目描述:

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.

第一想法就是dfs,这样写会超时:

public class Solution {    Map<String,Integer> map=new HashMap<String,Integer>();            public int minCut(String s) {        int min=Integer.MAX_VALUE;        if(isPalindrome(s))            return 0;        for(int i=0;i<s.length()-1;i++){            String substr=s.substring(0,i+1);            if(set.contains(substr)){                int cutnum=minCut(s.substring(i+1));                min=cutnum+1<min?cutnum+1:min;            }else{                if(isPalindrome(substr)){                    set.add(substr);                    int cutnum=minCut(s.substring(i+1));                    min=cutnum+1<min?cutnum+1:min;                }else{                    int cutnum=minCut(s.substring(0,i+1))+minCut(s.substring(i+1,s.length()))+1;                    min=cutnum+1<min?cutnum+1:min;                }            }        }        return min;    }}
后来我加了备忘录,然后想想这里每次调用substring函数很浪费时间,于是我换成了char[],速度快了很多,但还是超时了,WTF!

public class Solution {    Map<String,Integer> map=new HashMap<String,Integer>();        public int minCut(String s) {        return getMinCut(s.toCharArray(), 0,s.length()-1);    }public int getMinCut(char[] chars,int left,int right){String str=new String(chars, left, chars.length-left);if(map.containsKey(str))return map.get(str);if(isPalindrome(chars,left,right))        return 0;int min=Integer.MAX_VALUE;for(int i=left;i<right;i++){        String substr=new String(chars, left, i-left+1);        if(map.containsKey(substr)){        int leftCut=map.get(substr);        int rightCut=getMinCut(chars,i+1,right);        min=leftCut+rightCut+1<min?leftCut+rightCut+1:min;        }else{        if(isPalindrome(chars,left,i)){        map.put(substr,0);        int rightCut=getMinCut(chars,i+1,right);            min=rightCut+1<min?rightCut+1:min;        }else{        int leftCut=getMinCut(chars,left,i);//这个地方写成了i+1        int rightCut=getMinCut(chars,i+1,right);        min=leftCut+rightCut+1<min?leftCut+rightCut+1:min;        }        }        }map.put(str, min);        return min;}private boolean isPalindrome(char[] chars,int left,int right){while(left<right){if(chars[left]==chars[right]){left++;right--;}else{return false;}}return true;}}
这个题正确的自上而下的dfp算法:

这里在判断是否是回文数的时候直接在panMap中查找。

public class Solution {    int[][] panMap;    int[] map;    public int minCut(String s) {        panMap = new int[s.length()][s.length()];        map = new int[s.length() + 1];        Arrays.fill(map, Integer.MAX_VALUE);        map[s.length()] = 0;        return minCut(s, 0) - 1;    }    private int minCut(String s, int start) {        if (map[start] != Integer.MAX_VALUE) return map[start];        for (int i = start; i < s.length(); i++) {            //这里当start==i时肯定会执行            if (isPan(s, start, i)) {                map[start] = Math.min(map[start], 1 + minCut(s, i + 1));            }        }        return map[start];    }    private boolean isPan(String s, int start, int end) {        if (start == end) return true;        if (end == start - 1 && s.charAt(start) == s.charAt(end)) return true;        if (panMap[start][end] != 0) return panMap[start][end] == 1 ? true : false;        if (s.charAt(start) == s.charAt(end)) {            panMap[start][end] = isPan(s, start + 1, end - 1) ? 1 : -1;        }        return panMap[start][end] == 1 ? true : false;    }}
自下而上的dp算法:

This can be solved by two points:

  1. cut[i] is the minimum of cut[j - 1] + 1 (j <= i), if[j, i] is palindrome.
  2. If [j, i] is palindrome, [j + 1, i - 1] is palindrome, andc[j] == c[i].

public class Solution {    public int minCut(String s) {        char[] c = s.toCharArray();        int n = c.length;        int[] cut = new int[n];        boolean[][] pal = new boolean[n][n];            for(int i = 0; i < n; i++) {            //这里给min赋初始值            int min = i;            for(int j = 0; j <= i; j++) {                if(c[j] == c[i] && (j + 1 > i - 1 || pal[j + 1][i - 1])) {                    pal[j][i] = true;                      min = j == 0 ? 0 : Math.min(min, cut[j - 1] + 1);                }            }            cut[i] = min;        }        return cut[n - 1];    }}


0 0
原创粉丝点击