[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];

    }

}

  

你可能感兴趣的:(partition)