LeetCode之5:Longest Palindromic Substring
问题描述:
查找一个字符串的最长对称子序列。本文解法参考了[LeetCode] Longest Palindromic Substring 最长回文子串
问题的陷阱与难点:
- 能否在较短时间内理清逻辑,快速写出代码。
- 普通的向两边扩展查找最长字串的方法比较好想,但是存在较多重复操作。dp的解法比较难想出来。
缺陷代码分析(41.98%)
/**
* @program: xiaolajiao001
* @description: Longest Palindromic Substring
* @author: yi ao
* @create: 2019-02-20 16:32
*/
public class LeetCode5 {
int max = 0;
int left = 0,right = 0;
public String longestPalindrome(String s) {
if (s == null || s.length() == 0) {
return s;
}
int length = s.length();
boolean [][] dp = new boolean[length][length];
for (int i = 0; i < length; i++) {
for (int j = 0; j < i; j++) {
dp[j][i] = s.charAt(i) == s.charAt(j) && (i - j < 2 || dp[j + 1][i - 1] == true);
if (dp[j][i] == true && i - j + 1 > max) {
max = i - j + 1;
left = j;
right = i;
}
}
dp[i][i] = true;
}
return s.substring(left, right + 1);
}
}
**这道题主要考察的是思路,很容易在遍历的过程中产生重复的操作,所以如何能让之前判断好的结果辅助运用到后面的子串,这是典型的动态规划(dp)思想. **
思路
既然要用dp,肯定需要一个结构存储已经计算完毕的结果。
由于该题是求最长连续子序列,所有可能的子序列的个数是length2. 所以使用二维数组保存是最好的。
dp的核心就是前人栽树,后人乘凉。该题该怎样设计dp公式?
很容易想到的是,一个字符肯定是对称的,两个相等的字符也是对称的。除此之外,三个或三个以上的字符串则必须两端的两个字符相等,才有可能是对称的,因此,dp公式就得到了,假设array二维数组保存的是结果, i , j 分别代表字符串的左右边界下标,s代表的原始字符串:
二维数组 | 取值 | 条件 |
---|---|---|
array[i, j] | true | if i==j |
array[i, j] | s[i] == s[j] | if i + 1 = j |
array[i, j] | s[i] == s[j] && array[i+1][j-1] | if i + 1 < j |
如此以来,如果我们进行两层循环遍历,便可以像99乘法表那样,逐渐将从最小的字符串到最大的字符串的匹配结果得到。时间复杂度是O(n2)。
- 能不能将时间复杂度降低到小于O(n2)?