题目
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
示例 3:
输入:s = "a"
输出:"a"
示例 4:
输入:s = "ac"
输出:"a"
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母(大写和/或小写)组成
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-palindromic-substring
得到最长回文子串前,需要得到次最长子串。
例如字符串:cbbaabb ,它的最长回文子串为:bbaabb,得到该结果需要逐步确认: aa、baab 是回文,最终结论,bbaabb是回文子串。
类似此类需要依赖子问题结论的,求解都可以使用动态规划。
解题思路
有字符串:vxajkbbkja ,肉眼可判断最大回文为:ajkbbkja 如下图所示:我们只需要以中轴为起点,以途中红色箭头方向依次判断相等性,取到最长的即可。 (坐下部分对称,可以不必比较)
设横向为X, 纵向为Y,两个方向都从 字符v开始,字符a结束。延对称轴方向访问。
遍历如图红色箭头指向路径,如下每行对应一条红色箭头。 {0,0} {1,0} {1,1}{2,0} {2,1} {2,2}{3,1} {3,2} {3,3}{4,2} {4,3} {4,4}{5,3} {5,4} {5,5}{6,4} {6,5}{7,4}{8,3}{9,2} {6,6}{7,5} {7,6} {7,7}{8,6} {8,7} {8,8}{9,7} {9,8} {9,9}
最终得到相等的有点:{6,5}{7,4}{8,3}{9,2} 把它延对称轴映射:就可以得到最终的回文子串。
最终代码
我没有使用二维数组,所以节约了不少内存空间,由于增加了对特殊情况的判断,所以代码不是很简洁:
class Solution {
public String longestPalindrome(String s) {
char[] sArr = s.toCharArray();
int maxLetf = 0, maxLen = 0, curLeft = 0, curLen = 0;
boolean turnFlag = true, maxFlag = true;
int returnValue = 0;
for(int i = 0; i < sArr.length;){
int j = (turnFlag) ? i : i - 1;
for(; j >= 0 && i < sArr.length; j--,i++){
if (sArr[i] == sArr[j]) curLen++;
else break;
}
if (curLen != 0 && !turnFlag) curLen++;
if (curLen > maxLen || (curLen == maxLen && turnFlag)){
maxLen = curLen;
maxLetf = curLeft;
maxFlag = turnFlag;
}
turnFlag = !turnFlag;
if (turnFlag) i = returnValue;
else i = ++returnValue;
curLeft = i;
curLen = 0;
}
maxLetf = maxLetf - (--maxLen);
maxLen = maxFlag ? (maxLetf + maxLen + maxLen + 1) : (maxLetf + maxLen + maxLen);
return s.substring(maxLetf, maxLen);
}
}
设字符串长度为:N, X = N/2,如下公式表示需要对比的次数,可以很直观的得到结论,它就是二维表格一半格数近似和。
利用本题同样思路,可以解两个字符串的最大公共子串,异曲同工。
|