获得最长回文子序列的长度

时间:2014-11-11 17:29:12

标签: java algorithm

这个解决方案有效,但我不确定它是否可以改进。有没有人有任何想法?

class Ideone
{
    public static void main(String[] args) {    
        int arr[] = new int[] {4,1,2,3,4,5,6,5,4,3,4,4,4,4,4,4,4};  
        System.out.println(maxLengthPalindrome(arr, 0, arr.length-1));
    }

    public static int maxLengthPalindrome(int[] values, int i, int j) {
        if(j<=i) 
            return j-i+1;
        if(values[i]==values[j]) 
            return 2 + maxLengthPalindrome(values, i+1, j-1);
        else 
            return Math.max(maxLengthPalindrome(values, i+1, j), maxLengthPalindrome(values, i, j-1));      
    }
}

1 个答案:

答案 0 :(得分:2)

您的方法存在的问题是,它会导致对完全相同的子阵列进行多次重复调用。考虑这个顺序:

1 2 3 4 5

您将对这两个子数组进行递归调用:

2 3 4 5
1 2 3 4

反过来又涉及这些的递归调用:

3 4 5
2 3 4
2 3 4      // duplicate!
1 2 3

反过来涉及:

4 5
3 4
3 4        // duplicate!
2 3
3 4        // duplicate!
2 3        // duplicate!
2 3        // duplicate!
1 2

。 。 。你看到了问题。因此,总算法复杂度是指数的,O(2 n ),即使不同调用的总数只是二次,O( n < / EM> 2 )。

更好的方法是使用名为 dynamic programming (或“自下而上递归”)的东西:您可以使用 n × n 数组,用于跟踪每个子阵列中最长的回文子序列。从“底部”开始 - 在长度为1的每个子阵列中存储最长的回文子序列的长度,然后进入长度为2的子阵列,依此类推。在每次传球中,您都可以使用之前所有传球的结果。只有一个长度为 n 的子阵列,您想要的答案是最长的回文子序列的长度。

注意,对于每个传递(例如,长度为 m 的子阵列),实际上只需要前两次传递(长度 m -1的子阵列和子阵列长度 m -2),因此您可以使用两个长度为 n 的一维数组而不是一个大小为 n <的二维数组来优化空间/ EM>×名词的;但是,我不推荐在使用 n × n 数组之后进行优化(因为能够将所有先前结果打印为矩阵是可能对调试有帮助。)