# Leetcode – Longest Palindromic Substring (Java)

Finding the longest palindromic substring is a classic problem of coding interview. This post summarizes 3 different solutions for this problem.

1. Dynamic Programming

Let s be the input string, i and j are two indices of the string. Define a 2-dimension array "table" and let table[i][j] denote whether a substring from i to j is palindrome.

Changing condition:

```table[i+1][j-1] == 1 && s.charAt(i) == s.charAt(j)
=>
table[i][j] == 1
```

Time O(n^2) Space O(n^2)

```public String longestPalindrome(String s) { if(s==null || s.length()<=1) return s;   int len = s.length(); int maxLen = 1; boolean [][] dp = new boolean[len][len];   String longest = null; for(int l=0; l<s.length(); l++){ for(int i=0; i<len-l; i++){ int j = i+l; if(s.charAt(i)==s.charAt(j) && (j-i<=2||dp[i+1][j-1])){ dp[i][j]=true;   if(j-i+1>maxLen){ maxLen = j-i+1; longest = s.substring(i, j+1); } } } }   return longest; }```

For example, if the input string is "dabcba", the final matrix would be the following:

```1 0 0 0 0 0
0 1 0 0 0 1
0 0 1 0 1 0
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
```

From the table, we can clearly see that the longest string is in cell table.

2. A Simple Algorithm

We can scan to both sides for each character. Time O(n^2), Space O(1)

```public String longestPalindrome(String s) { if (s.isEmpty()) { return null; }   if (s.length() == 1) { return s; }   String longest = s.substring(0, 1); for (int i = 0; i < s.length(); i++) { // get longest palindrome with center of i String tmp = helper(s, i, i); if (tmp.length() > longest.length()) { longest = tmp; }   // get longest palindrome with center of i, i+1 tmp = helper(s, i, i + 1); if (tmp.length() > longest.length()) { longest = tmp; } }   return longest; }   // Given a center, either one letter or two letter, // Find longest palindrome public String helper(String s, int begin, int end) { while (begin >= 0 && end <= s.length() - 1 && s.charAt(begin) == s.charAt(end)) { begin--; end++; } return s.substring(begin + 1, end); }```

3. Manacher's Algorithm

Manacher's algorithm is much more complicated to figure out, even though it will bring benefit of time complexity of O(n). Since it is not typical, there is no need to waste time on that.

Category >> Algorithms
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
```<pre><code>
String foo = "bar";
</code></pre>
```
• Bharathi rv

y keep two helper method call in second solution. both helper call does same right? how it works second helper return value replace the first helper returned value right then y keep this extra second method call?

• Snehasish Ghosh

” aba ” will also work, that is also an option

• Snehasish Ghosh

code

• Snehasish Ghosh

Can’t you do it yourself ? Go back to the text books and read about Asymptotic

• Snehasish Ghosh

yeh , the DP solution doesn’t work for me either. Can any one fix it

• Siliang Liu

the second approach are not optimal, if we have

• ryanlr

Correct. Like this

• Kiko

Both sides of the entire string? So each character is like a mid-point, and then all the characters to the left are tested if they’re a palindrome, vice versa with right side?

• ryanlr

For each character, scan to both sides and get the longest palindromic sub-strings.

• Kiko

Hi, can you explain the second “simple” algorithm in more detail? I understand the first algorithm because its plain to see how it works with the 2D array. But I can’t really visualize the second one.

• Bukary Kandeh

Here is my implementation. Simple and efficient
``` public String LongestPalindrome(String s) { if(s == null || s.length() == 0) return null; if(s.length() == 1) return s;```

``` StringBuilder longestPalin = new StringBuilder(); int max = 0; ```

``` for (int i = 0; i < s.length(); i++) { for (int j = i + 2; j max) { longestPalin.setLength(0); longestPalin.append(sb.toString()); max = sb.toString().length(); } } } return longestPalin.toString(); } ```

• Shravan Kumar Sridhara

Hi Doesnt the code given under dynamic programming section throw a index out of bounds exception when l=s.length()-2 and i=s.length()-1. then j=i+l which is 2.s.length()-3. So s.charAt(j) gives index out of bounds exception

• wu

in scala

“`
def findPS(os: String) = {
def isPS(s: String): Boolean = s == s.reverse
val idxedS = os.toList.zip(0 until os.length)
val idxDict = idxedS
.groupBy[Char]{ case (c, idx) => c }
.map {case (c, tps) => (c, tps.map(_._2).sorted.reverse)}
var (psLength, psStr) = (1, “”)
idxedS.foreach { case (c, idx) =>
idxDict(c).takeWhile(_ > idx).foreach { nIdx =>
os.substring(idx, nIdx + 1) match {
case subS if isPS(subS) && nIdx-idx > psLength =>
psLength = nIdx – idx + 1
psStr = subS
case _ => ()
}
}
}
psStr
}
“`

• Lakshminarayan Kamath

public class LongestPalindrome
{
public static void main(String[] args)
{
String input=”abccbp”;
String longest=longestPalindrome(input);
System.out.println(longest);
}

public static String longestPalindrome(String input)
{
if(input.isEmpty())
return input;

if(input.length()==1)
return input;

String longest=””;
String output=””;
int length=0;

for(int i=0;i<input.length();i++)
{
longest="";

for(int j=i;jlength)
{
length=longest.length();
output=longest;
}
}
}
}

return output;
}
}

• CRH

I think Solution 3 expects the characters to be adjacent. This question usually is just about finding longest NOT necessarily contiguous substring. The recursive approach of this problem will be exponential time, 2^n . But using dynamic programming time can be reduced to n^2

• 卢刘杰

yep ! u are right. the objective is to make the length between i and j is 3.

• 卢刘杰

I suppose u at wrong at some point.

• Harish

ABCCBP iis working fine. But incase I give ABCDA, the longest possible palindrome is ‘AA’ but it is showing ‘A’. Hope I didn’t unnderstand it wrong..!

• NotActually An FormulaFan

I did this in pseudo code since I am novice at Java
test: “satdoggodabca”
–main:
—-loop (idx=0;idx<length;idx++):
——get char (baseChar) at idx
——loop:
——–find char again in test (testChar)
——–test if testChar– matches baseChar++, loop until indexes are equal, store if equal

visual representation:

1. satdoggodabca

2. s_____________ (no other 's' found) t: length

3. _a________a__a (test if inner characters of found 'a' match the next character of the other 'a') t:length – 1

3. _at______da_ca ( no matches here, continue) t: # of found chars

4. __t___________ ( none for 't') t: length – 3

5. ___d_____d___ ( test 'd') t: length – 4

5. ___do__od___ ( looking good) t: # of found chars

5. ___doggod___ (yeeee, also note since it is left most and we started by whole string scanning, we can assume this is the longest palindrome)

estimated worst time: O(n * (n-k))

• Youchen

The DP solution above did not pass the test case which is the “aaa…aabcaa…aaa”, its length is 1,000 and the ‘b’ is in index 498. OJ shows that “Time Limit Exceeded”.

• Salil Surendran

What do you guys think of this solution. This is an O(n) solution

private String findLongestPalindromicSubString(String str){

if(str == null || str.length() == 0)
return null;
else if(str.length() == 1)
return str;
else{
//Traverse down the string and which is each character
//check this logic.
int index=1;
String longestPalindrome=null;
while(index < str.length()/*||
(longestPalindrome != null && str.length() – index 2 && str.charAt(index) == str.charAt(index – 2))

if(currentPalindrome != null){
if(longestPalindrome == null || currentPalindrome.length() > longestPalindrome.length())
longestPalindrome=currentPalindrome;
index+=currentPalindrome.length() / 2;
}else
index++;
}
return longestPalindrome;
}
}

• YouYouMe

The bounds checking of the helper function is wrong. Why does the helper func return the substring from begin + 1? and what if the while loop breaks at end = s.length?

If the loop breaks before begin < 0 and before end = s.length it should just return substr(begin, end).

so somethin like:

if (begin s.length – 1) end = s.length -1;

return s.substring(begin, end);

• Sweta Shah

Hello,

Can someone let me know what is the time and space complexity for my solution to this problem below?

``` public static String longestPalindrome(String[] stringArray) { if (stringArray.length == 1) { return stringArray; } if (stringArray.length == 0) { return null; } int maxLength = 0; String longestPal = ""; for (final String eachString : stringArray) { if (isPalindrome(eachString) && eachString.length() > maxLength) { maxLength = eachString.length(); longestPal = eachString; } } return longestPal; }```

``` ```

``` public static boolean isPalindrome(String testStr) { int i = 0, j = testStr.length() - 1; while (i != j) { if (testStr.charAt(i) == testStr.charAt(j)) { i++; j--; } else { return false; } } return true; } ```

• Guest

``` public static void main(){```

``` ```

```} ```

• Guest

Hello,

Can someone let me know what would be the time and space complexity of my solution here?

public static String longestPalindrome(String[] stringArray) {

if (stringArray.length == 1) {

return stringArray;

}

if (stringArray.length == 0) {

return null;

}

int maxLength = 0;

String longestPal = “”;

for (final String eachString : stringArray) {

if (isPalindrome(eachString) && eachString.length() > maxLength) {

maxLength = eachString.length();

longestPal = eachString;

}

}

return longestPal;

}

public static boolean isPalindrome(String testStr) {

int i = 0, j = testStr.length() – 1;

while (i != j) {

if (testStr.charAt(i) == testStr.charAt(j)) {

i++;

j–;

} else {

return false;

}

}

return true;

}

• JY

In addition, the outer loop should be. Not necessary, but makes more sense.
for (int i = 0; i < length-1; i++)

• JY

I think Kishore is talking about solution 1, public static boolean isPalindrome(String s);. Since this method is checking whether the passed string instance is a palindrome or not, you only need to iterate half of its length; otherwise, we are checking the same value twice if the string is palindrome.

• heena

For more programs Refer http://javatutorialhere.blogspot.in/

• ramesh

to reduce the number of iterations in the first case

public static boolean isPalindrome(String s) {
int j = (s.length()%2)!=0?(s.length()/2):((s.length()/2)+1);
int i=0;
for (i = 0; i < j; i++) {
if (s.charAt(i) != s.charAt((s.length() – 1) – i)) {
return false;
}
}
return true;
}

• drake

@Pankaj: Did you run the program? I executed with ABCCP as input string the output was BCCB

• ryanlr

You may want to run the code again. I used “ABCCBP” to test, and it worked.

• Pankaj

This would not work correctly, ex. ABCCBP. It wont be able to find exact longest palindrom which is BCCB

• Learner

Can anyone help me finding the complexity of this? ->
private static boolean checkPaliSubstring(String str1) {
boolean paliSubstr = false;
int longestlen = 0;

String sub1 = str1.substring(1);
if(checkPalindrome(sub1) && sub1.length()>longestlen){
longestSubPalindrome= sub1;//class field
longestlen = sub1.length();
paliSubstr = true;
}

String sub2 = str1.substring(0, str1.length()-1);
if(checkPalindrome(sub2) && sub2.length()>longestlen){
longestSubPalindrome= sub2;//class field
longestlen = sub2.length();
paliSubstr = true;
}

if(!paliSubstr && sub1.length()!=2){
checkPaliSubstring(sub1);
}

if(!paliSubstr && sub2.length()!=2){
checkPaliSubstring(sub2);
}

return paliSubstr;//substring palindrome exists or not
}

• Codethecode

Can we put indices of all occurrences of chars in a hash table and then pursue just ones with count >2 ? Could be simpler IMO

• thundear

table[i][i] and table[i][i+1] is calculated in the first two for loop.
l=3 to start the third for loop is to solve the condition that table[i][j] where the gap between i and j is above 2.

• Mallikarjun

Sorry. Wrong Optimization. Found a scenario where it can fail. Your one is the correct one.

• Mallikarjun

I feel, can be slightly optimized of we jump to end of the present max. something like this. Observe for j. (Let me know whether it is correct or can miss some scenarios).

int j=0;
String longest = s.substring(0, 1);
for (int i = 0; i longest.length()) {
longest = tmp;
j = tmp.length()/2;
}

// get longest palindrome with center of i, i+1
tmp = helper(s, i, i + 1);
if (tmp.length() > longest.length()) {
longest = tmp;
j = tmp.length()/2;
}

• Mallikarjun

There could be the palindrome in the second half. It always need not be the spread around the center.

• Faris

How can i find the longest str by using the final matrix?

• Kishore

In the isPalindrome method, the checking can only be done till

i < s.length()/2

• Yash

In the DP solution why is the l in the first for loop set to 3?

• ryanlr

Good Algorithm.

• Yifan

My solution: Time O(n^2) Space O(1)

public String longestPalindrome(String s) {
if (s.isEmpty()) {
return null;
}

if (s.length() == 1) {
return s;
}

String longest = s.substring(0, 1);
for (int i = 0; i longest.length()) {
longest = tmp;
}

// test s[i,i+1]
tmp = helper(s, i, i + 1);
if (tmp.length() > longest.length()) {
longest = tmp;
}
}
return longest;
}

// [begin, end]
public String helper(String s, int begin, int end) {
while (begin >= 0
&& end <= s.length() – 1
&& s.charAt(begin) == s.charAt(end)) {
begin–;
end++;
}
return s.substring(begin + 1, end);
}