[leetcode]Palindrome Partitioning II

这道题是DP。那么一开始很自然的想出了O(n^3)的方法。就是预处理是否是Palindrome的boolean[][],话费O(n^3)。然后处理i到j段件的cut数目int[][]也花O(n^3)时间,因为i和j两层循环,中间又要遍历一次i和j之间的分割点。

但是网上看了一下两者都可以化简到O(n^2)。前者也是个DP,因为valid[i][j]依赖于valid[i+1][j-1]和s[i]==s[j]。而后面其实多求了许多不需要的信息,我们只要cut[0][j]就行了,而这里把所有的cut[i][j]都求了。这有点像Floyd算法求了所有点之间最短距离,所以复杂度就比Dijkstra高了一维类似。所以后者的转移方程式cut[i]为cut[j]+1,如果valid[j+1][i]的话。这里要注意的是,如果valid[i][j],那么直接就是0,因为不用再分割了。实现的时候这里错了。

public class Solution {
    public int minCut(String s) {
        int len = s.length();
        boolean[][] valid = new boolean[len][len]; // 0-len-1
        for (int L = 0; L < len; L++) // L: j-i
        {
            for (int i = 0; i < len; i++)
            {
                if (L+i>=len) continue;
                if (L==0) valid[i][i] = true;
                else if (L==1) valid[i][i+L] = s.charAt(i)==s.charAt(i+L);
                else
                {
                    valid[i][i+L] = s.charAt(i)==s.charAt(i+L) && valid[i+1][i+L-1];
                }
            }
        }
        int[] cut = new int[len]; // the cuts for 0 to i
        cut[0] = 0;
        for (int i = 1; i < len; i++)
        {
            if (valid[0][i]) cut[i] = 0;
            else
            {
                cut[i] = Integer.MAX_VALUE;
                for (int j = 0; j < i; j++)
                {
                    if (valid[j+1][i] && cut[j]+1 < cut[i])
                        cut[i] = cut[j]+1;
                }
            }
        }
        return cut[len-1];
    }
}

  

原文地址:https://www.cnblogs.com/lautsie/p/3348037.html