leetcode——5.Longest Palindromic Substring(java),
leetcode——5.Longest Palindromic Substring(java),
题目:找到最大的回文子串
首先,回文串就是左右对称的字符串。要解这道题首先应该知道如何判断一个字符串是否是回文串。
我的思想很简单,就是定义两个指针i,j,初始指向字符串头和尾,依次向里收缩。长度为奇数的字符串最后两个指针相遇,即i=j。长度为偶数的字符串最后相邻,即j=i+1。直到最后,若i和j满足上面的这个条件,则说明该字符串是回文串。然后再通过遍历,找到最长的回文子串。这个算法的复杂度应该是O(n^2) 。
我想上面这种算法应该是最容易想到的一种算法。但是要注意一下,在获得一个回文子串时,保存当前的长度,下次遍历的时候窗口最小设为这个长度,这样可以稍微减少一点运算时间。比如:在第一提交代码时我没有考虑这个问题,leetcode会报Time Limit Exceeded ,输入字符串为1000个d,这个字符串如果没有考虑窗口大小的话就会从第一位d开始,一直遍历到最后一位,然后确定这整个字符串是一个回文串,但是还会从第二位d开始继续遍历,但其实后面的子串长度肯定不会超过第一次的长度。所以后面的操作是没有意义的。
class Solution {
public boolean isPalindrome(String s){
boolean isOrNot = true;
int size = s.length();
int i=0,j = size-1;
while(j>=i){
char c1 = s.charAt(i);
char c2 = s.charAt(j);
if(c1 == c2){
i++;
j--;
}else{
isOrNot = false;
break;
}
}
return isOrNot;
}
public String longestPalindrome(String s) {
if(s.length()==0){
return s;
}
int location = 0;
int size = 1; //最大窗口值
int i = 0; //左侧指针
int j = 1; //右侧指针
while(i<s.length()-1&&j<s.length()){
String substring = s.substring(i, j+1);
if(isPalindrome(substring)){
if(size < j-i+1){
size = j-i+1;
location = i;
}
}
j++;
if(j==s.length()) {
i++;
j = i+size;
}
}
String ans = s.substring(location,size+location);
return ans;
}
}
考虑优化算法,用动态规划可以减少运行时间。
下面考虑动态规划算法。
判断一个字符串是否是回文串,只要首字符和尾字符相等,然后中间剩下的部分也是回文串,那么整个字符串就是回文串,如果首字符和尾字符不相等,那么一定不是回文串。考虑边界,若只有一个字符,则肯定是,若相邻,首字符尾字符相等也肯定是回文串,当字符串长度大于2时,若首尾相同,判断中间部分是否是回文串即可。
这样我们需要定义一个标志数组,存储从当前是否时回文串。label[i][j] 表示从i到j位的子串是否是回文串。
看下面这个例子 :输入串为“babad"
标志数组为(将其初始化全为0,只更新i<=j的部分)下表行代表i,列代表j值
i,j | 0 | 1 | 2 | 3 | 4 |
0 | 1 | 0 | 0 | 0 | 0 |
1 | 0 | 1 | 0 | 0 | 0 |
2 | 1 | 0 | 1 | 0 | 0 |
3 | 1 | 1 | 0 | 1 | 0 |
4 | 0 | 0 | 0 | 0 | 1 |
当更新标志数组时,同时判断子串长度,如果是回文串,就判断是否应该更新最大子串长度和此时的i值。算法结束后,可以由子串长度和子串开始位置得到该最长子串。
class Solution {
public String longestPalindrome(String s){
int size = s.length();
int [][]label = new int[size][size]; //标志数组
int maxLength = 0; //存储最长子串的长度
int location = 0; //存储最长子串的起始位置
int i = size-1 , j = size-1; //初始时 i,j都为最后一位下标
while(i>=0){
j = i;
while(j<size){
char c1 = s.charAt(i);
char c2 = s.charAt(j);
if(c1==c2){
if(j-i<2){
label[i][j] = 1;
}else{
label[i][j] = label[i+1][j-1];
}
}else{
label[i][j] = 0;
}
if(label[i][j]==1&&maxLength<j-i+1){
maxLength = j-i+1;
location = i;
}
j++;
}
i--;
}
String ans = s.substring(location,maxLength+location);
return ans;
}
}
相关文章
- 暂无相关文章
用户点评