这个解决方案有效,但我不确定它是否可以改进。有没有人有任何想法?
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));
}
}
答案 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 数组之后进行优化(因为能够将所有先前结果打印为矩阵是可能对调试有帮助。)