题目:
最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
注:回文字符串就是该字符串正着读和倒着读的顺序一模一样。
一、算法介绍&解题思路
- 算法:动态规划,时间复杂度和空间复杂度都为O(n^2),是一种空间换时间的方式。
- 思路:一个回文子串去掉两头以后,剩下的部分依然是回文子串。
- 状态:dp[i][j]表示子串s[i…j]是否为回文子串。
- 状态转移方程:dp[i][j] = (s[i]==s[j]) and dp[i+1][j-1]
- 边界条件:j-1-(i+1)+1<2,整理得 j-i<3,等价于 j-i+1<4,也就是s[i…j]长度为2或3时,不用检查子串是否是回文。(因为是访问下标的方式,所以要考虑下标有效的情况,也就是要考虑边界的情况)
【解释:如果子串两头元素相等,长度又是2或3,那该子串肯定是回文的,所以无需再检查】 - 初始化:dp[i][j] = true;对角线的位置是单个字符,所以也是回文的。
- 输出:在得到一个状态是true的时候,记录起始位置和长度,填表完成以后再截取。
图示过程如下(由于i是小于j的所以计算容器的上半部分即可):
二、解题思路转换为代码
1、定义一个maxLen变量来存储最大回文子串的长度,一个begain变更来存放最大回文子串的开始下标;
2、判断字符串的的长度s.length()是否小于2,如果是的话说明该字符串是一个单字符直接返回即可;
3、定义一个状态容器 boolean[][] dp = new boolean[len][len],长度为字符串长度的二维数组,将对角线的位置直接定义为true;
4、将字符串转换为字符数组:char[] ch = s.toCharArray();
1)循环for(int j = 1, j < len, j++),for(int i = 0, i < j, i++),判断ch[i]==ch[j],若为false,则dp[i][j] = false;
2) 若ch[i]==ch[j],若为ture,则判断 j-i<3是否成立,若成立则dp[i][j] = true;
3)若 j-i<3不成立,则将dp[i+1][j-1]赋值给dp[i][j];
4)判断dp[i][j]&&j-i+1>maxLen,成立的话,将i赋给begain,j-i+1赋给maxLen,最长的回文子串就是s.subString(begain,begain+maxLen);
三、代码:
package suanfa;
/*
5、最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释