Longest Palindromic Substring笔记
这是一道在leetcode上看到的题目
一开始,我能想到的思路是蛮力法:
就遍历每个字符,然后对每个字符都尝试从1到n的长度,看有没有回文串,并记录以该字符起始的回文串的最大长度。
这个思路其实没有上手实现,因为和前面的那题求最大没有重复字符的substring的原始思路一样,时间复杂度是O(n^3),是超时的。
然后是可以通过的方法:
两边扩展法:
抓住,回文串是轴对称的这个特点,即一个中心往两边探索,两边都是相等的。
实现上先要遍历每个字符,从0序号到s.length()-2序号,这里的遍历,是把它们作为中心。
然后每个中心,进行两个判断:
1.以这个字符为中心可能有字符个数为奇数的回文串,即以这个字符为中心,往两边扫描,两边的都相等。 扫描到不相等的地方,记下长度,就是以该字符为中心的最大的奇数回文串的长度。
2.以这个字符为中心可能有字符个数为偶数的回文串,即这个时候的对称中心为两个字符——像例如abccba,当遍历到c元素的时候,如果只是以它为中心,往两边扩散,会立刻发现b!=c,然后就判断不出是回文串了。
因此遍历的时候要对每个字符都进行两次判断,时间复杂度为O(n^2)
class Solution { /**
*用的思路是 遍历每个元素,然后对每个元素进行两边扫描,扫描的同时可以判断是否回文串了,因为回文串必定是轴对称。 *对每个元素两边扫描的时候要分两种情况:
1.因为以一个元素为中心,可能构成奇数个字符的 回文串,也就是只关于那个元素对称;
2.又或者是构成偶数个字符的 回文串,这个时候就不止关于那个元素对称,还有它旁边的元素,例如abccba,当遍历到c元素的时候,如果只是以它为中心,往两边扩散,会立刻发现b!=c,然后就判断不出是回文串了。
因此遍历的时候要对每个字符都进行两次判断,时间复杂度为O(n^2)
*/
public String longestPalindrome(String s) { if(s.length() == 1)return s; //因为 如果s长度为1,进不了下面那个for循环…… int longestPalindromeLength = 0; String longestPalindromeStr = ""; for(int i = 0; i < s.length() - 1; i++) {
//遍历每个字符,以每个字符为中心 进行判断以这个 字符为中心的所有字符串中有没 回文字符串,并求出最大的那个
int oddLongestLength = findLongestPalindrome(s, i);
if(oddLongestLength > longestPalindromeLength) {
longestPalindromeLength = oddLongestLength;
longestPalindromeStr = s.substring(i - oddLongestLength/2, i + oddLongestLength/2 + 1);//注意这个subString后面那个index是不取的……
} int evenLongestLength = findLongestPalindrome(s, i, i + 1);
if(evenLongestLength > longestPalindromeLength) {
longestPalindromeLength = evenLongestLength;
longestPalindromeStr = s.substring(i + 1 - evenLongestLength/2, i + evenLongestLength/2 + 1);//注意这个subString后面那个index是不取的……
}
} return longestPalindromeStr;
} /**
* 以一个index为中心,找以它为中心的 所有 回文字符串 而且是 字符个数为奇数的回文字符串,因为偶数的话,中心应该是两个。
* @param s 字符串
* @param centerIndex 中心字符的index
* @return 那个最长的 回文字符串的 长度
*/
private int findLongestPalindrome(String s, int centerIndex) {
int tempLongestLength = 0;//代表以这个centerIndex为中心的所有回文串中的 最大 for(int i = centerIndex, j = centerIndex; i >= 0 && j <= s.length() - 1; i--, j++) {
if(s.charAt(i) == s.charAt(j)) {
//说明出现了 一个回文串了
if( (j - i + 1) > tempLongestLength ) {
tempLongestLength = j - i + 1;
}
} else {
//如果不相等,说明不对称 直接break了
break;
}
}
return tempLongestLength;
} /**
* 找以 这两个index为中心,个数为偶数的 所有 的回文字符串
* @param s 字符串
* @param leftCenterIndex 左边中心
* @param rightCenterIndex 右边中心
* @return 这两个中心拓展的最长 的 回文字符串的长度
*/
private int findLongestPalindrome(String s, int leftCenterIndex, int rightCenterIndex) {
int tempLongestLength = 0;//代表以这个centerIndex为中心的所有回文串中的 最大 for(int i =leftCenterIndex, j = rightCenterIndex; i >= 0 && j <= s.length() -1; i--, j++) {
if(s.charAt(i) == s.charAt(j)) {
//说明出现了 一个回文串了
if( (j - i + 1) > tempLongestLength ) {
tempLongestLength = j - i + 1;
}
} else {
//如果不相等,说明不对称 直接break了
break;
}
}
return tempLongestLength; }
}
动态规划法:
用一个二维数组来求解,dp[i][j]的值标识,字符串中从i到j是不是回文串。
dp[i][j]=1,我们只要想办法把二维数组填好后,找出j - 1 + 1最大的值,求出子串序列返回即可。
填二维数组的时候有几个情况:
1.单个字符的时候,也就是dp的对角线i==j的时候,肯定为1;
2.相邻字符的时候,也就是dp中j - i < 2的时候,只有两个相同才为1,即s.charAt(i)==s.charAt(j)时有dp[i][i + 1] = 1;
3.字符相隔大于2的时候,也就是j - 1 >= 2的时候,这个时候值为1,需要边缘两个值相等,也就是s.charAt(i)==s.charAt(j);还有中间也是回文串——也即dp[i+1][j-1] == 1
具体代码实现的话,分三轮遍历来
首先有个二维数组,然后:
1.第一轮遍历,单个字符是回文串,也就是dp[i][i] = 1;
2.第二轮遍历,相邻字符是不是回文串呢?遍历看相邻字符是不是相等的,即s[i]和s[i + 1]相等的话则有dp[i][i + 1] = 1,即j - 1 == 1的情况;
3.第三轮遍历,真正的动态规划,刚刚把数组dp中对角线上的还有dp[i][j]i和j间隔为1的也就j - 1 < 2的情况的空都填了,现在要做的是利用前面数组的结果,填dp数组中j - i >= 2的格子。第三轮遍历是个二重循环,j - i >=2时,进行遍历,然逐渐增大j和i的距离。只有s[i] == s[j],且dp[i + 1][j - 1]为1两者都成立的情况下,dp[i][j] = 1。
算法Time:O(n^2), Space:O(n^2)。
代码:(引用自——https://www.cnblogs.com/clnchanpin/p/6880322.html)
public String longestPalindrome(String s) {
if (s == null)
return null; if(s.length() <=1)
return s; int maxLen = 0;
String longestStr = null; int length = s.length(); int[][] table = new int[length][length]; //every single letter is palindrome
for (int i = 0; i < length; i++) {
table[i][i] = 1;
longestStr = s.charAt(i) + ""; //此时 最大的 回文串就是 单个字咯
maxLen = 1;//最大回文串长度就为1咯
} //two consecutive same letters are palindrome
for (int i = 0; i <= length - 2; i++) { if (s.charAt(i) == s.charAt(i + 1)){//相隔的两个字相等
table[i][i + 1] = 1;
longestStr = s.substring(i, i + 2);
maxLen = 2;//两个相等的字符串嘛
}
} //condition for calculate whole table
//前面对于单个字也就是二维数组中对角线上的情况还有 间隔相等的情况 也就是j - i = 1的情况都处理了
//这里是 对其他需要 借助动态规划也就是之前数组的结果来操作的情况 也就是 j - 1 >=2的情况
for (int len = 3; len <= length; len++) {
/*第一层循环 是以长度为基准的,因为这里处理的是j - i >=2的情况嘛,也就是比如abc,a和c这样的情况,也就是子串长度3以上的情况,所以第一层循环就描述这个,从3开始慢慢加
*直到table[0][length - 1]填好就可以有结果了
*/ for (int i = 0; i < length - len + 1; i++) {
//这个条件是 因为len = j - 1 + 1,然后又有j < length得来的 (后面补充:)没那么复杂……就比如len是2,i是0,那么j的坐标就应该是i+2-1=1,所以就i+len-1<length即可 int j = len + i - 1;//len = j - 1 + 1 if(s.charAt(i) == s.charAt(j) && table[i + 1][j - 1] == 1) {
table[i][j] = 1;
if(len > maxLen) {
longestStr = s.substring(i, j + 1);
}
} else {
table[i][j] = 0;
} }
} return longestStr;
}
还有个很出名的Manacher 算法,时间复杂度为O(n),具体的一时半会没看懂,以后需要再找资料吧~
Longest Palindromic Substring笔记的更多相关文章
- (python)leetcode刷题笔记05 Longest Palindromic Substring
5. Longest Palindromic Substring Given a string s, find the longest palindromic substring in s. You ...
- 领扣-5 最长回文子串 Longest Palindromic Substring MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法)
Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法) Given a string s, find the longest pal ...
- 最长回文子串-LeetCode 5 Longest Palindromic Substring
题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...
- leetcode--5. Longest Palindromic Substring
题目来自 https://leetcode.com/problems/longest-palindromic-substring/ 题目:Given a string S, find the long ...
- [LeetCode] Longest Palindromic Substring 最长回文串
Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...
- No.005:Longest Palindromic Substring
问题: Given a string S, find the longest palindromic substring in S. You may assume that the maximum l ...
- Leetcode Longest Palindromic Substring
Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...
- 【leedcode】 Longest Palindromic Substring
Given a , and there exists one unique longest palindromic substring. https://leetcode.com/problems/l ...
随机推荐
- OC-内存管理的所有权链问题
背景: 最近维护之前的项目,没有注意具体的对象之间的关系,导致了一个bug. 让我了解到对象的所有权链问题. 需要内存管理的知识: 众所周知,oc是使用引用计数来管理内存的(当一个对象被持有,他的re ...
- excel 基本用法
- 洛谷 P4660 & bzoj 1168 [ Baltic OI 2008 ] 手套 —— 分析+单调栈
题目:https://www.luogu.org/record/show?rid=12702916 https://www.lydsy.com/JudgeOnline/problem.php?id=1 ...
- hibernate学习三 精解Hibernate之核心文件
一 hibernate.cfg.xml详解 1 JDBC连接: 2 配置C3P0连接池: 3 配置JNDI数据源: 4 可选的配置属性: 5 hibernate二级缓存属性 6 hibernate事务 ...
- dubbo框架介绍
1.背景 (#) 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进. 单一应用架构 当网站流量很小 ...
- 1.16 sqoop options-file参数进行运行任务
sqoop的options-file参数可以像hive的-f 参数那样,执行一个脚本文件,而不是直接在命令行执行: 其中,此脚本文件要遵循一定的格式:参考链接:http://sqoop.apache. ...
- c/c++面试45-50之字符串
45 使用库函数将数字转换为字符串,下面是常用库函数 (1) itoa():将整型转换为字符串 (2)ltoa():将长整形转换为字符串 (3)gcvt():将浮点转换为字符串 46 不使用库函数将整 ...
- Flutter实战视频-移动电商-33.列表页_子类和商品列表交互效果
33.列表页_子类和商品列表交互效果 主要实现点击小类下面的列表跟着切换 获取右侧下面的列表信息,即要传递大类的id也要传递小类的,所以需要把左侧的大类的id也要Provide化 可以看下网站上的接口 ...
- UVaLive 3695 City Game (扫描线)
题意:给定m*n的矩阵,有的是空地有的是墙,找出一个面积最大的子矩阵. 析:如果暴力,一定会超时的.我们可以使用扫描线,up[i][j] 表示从(i, j)向上可以到达的最高高度,left[i][j] ...
- Fitnesse 访问日志配置
1. 在build.xml中修改Finesse运行时的参数 <target name="run" depends="compile, compile-bootstr ...