150NeetCode 150

103.Longest Palindromic Substring

MediumBlind 751-D Dynamic Programming · 5/12
LeetCode #5Video

Problem

Given a string s, return the longest contiguous substring of s that reads the same forwards and backwards.

If several palindromes share the maximum length, any one of them is accepted.

Examples

Input:  s = "babad"
Output: "bab"
Explanation: "aba" is also a valid answer — both have length 3.
Input:  s = "cbbd"
Output: "bb"
Explanation: An even-length palindrome centred between the two b's.
Input:  s = "a"
Output: "a"

Constraints

  • 1 <= s.length <= 1000
  • s consists of only digits and English letters.

💡 Key Insight

A substring s[i..j] is a palindrome iff its ends match and its inside s[i+1..j-1] is a palindrome: pal(i, j) = s[i] == s[j] && pal(i + 1, j - 1), with every length-0 or length-1 string a palindrome. That recurrence gives an O(n²) DP. Flipping it around, every palindrome grows outward from a centre (a character or the gap between two), so expanding from all 2n - 1 centres finds the answer in O(n²) time with O(1) space. Manacher's algorithm reuses the mirror image of already-found palindromes to make the expansions linear overall — O(n).

Brute Force

TimeO(n³)SpaceO(1)

Intuition

Check every substring with a two-pointer palindrome test and keep the longest one that passes.

Algorithm

  1. For every i and every j >= i:
  2. Test s[i..j] by moving pointers inward from both ends.
  3. If it is a palindrome and j - i + 1 beats the best length, record start = i, bestLen = j - i + 1.
  4. Return s.substring(start, start + bestLen).

Visualization

s = "cbbd"
len 1: c b b d          all palindromes → best = "c"
len 2: cb ✗  bb ✓  bd ✗  → best = "bb"
len 3: cbb ✗ bbd ✗
len 4: cbbd ✗
answer "bb"

Code

java
class Solution {
    public String longestPalindrome(String s) {
        int n = s.length();
        int start = 0, bestLen = 1;
        for (int i = 0; i < n; i++) {
            for (int j = i + bestLen; j < n; j++) { // only lengths that could beat the best
                if (isPalindrome(s, i, j)) {
                    start = i;
                    bestLen = j - i + 1;
                }
            }
        }
        return s.substring(start, start + bestLen);
    }

    private boolean isPalindrome(String s, int lo, int hi) {
        while (lo < hi) {
            if (s.charAt(lo++) != s.charAt(hi--)) {
                return false;
            }
        }
        return true;
    }
}

Complexity

  • Time: O(n³) — O(n²) substrings, each checked in O(n).
  • Space: O(1) — only indices.

Complexity Comparison

Approach Time Space
Brute Force O(n³) O(1)
Top-Down Memoization O(n²) O(n²)
Bottom-Up Tabulation O(n²) O(n²)
Expand Around Center O(n²) O(1)
Manacher's Algorithm O(n) O(n)

Common Pitfalls

  • Only expanding odd-length centres — "cbbd" would return "c" instead of "bb".
  • Filling the DP table with i increasing: dp[i + 1][j - 1] would not be ready yet.
  • Off-by-one when converting an expansion back to a substring: after the loop the palindrome is s[l+1 .. r-1], not s[l .. r].
  • Confusing this with Longest Palindromic Subsequence — here the characters must be contiguous.
  • In an interview, Expand Around Center is the expected answer; mention Manacher as the O(n) follow-up.