Longest Palindromic Subsequence
MedPrompt
Given a string s, find the longest palindromic subsequence's length in s.
A subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements.
Example 1:
Input: s = "bbbab"
Output: 4
Explanation: One possible longest palindromic subsequence is "bbbb".Example 2:
Input: s = "cbbd"
Output: 2
Explanation: One possible longest palindromic subsequence is "bb".
Constraints:
1 <= s.length <= 1000sconsists only of lowercase English letters.
Approaches
3 approaches with complexity analysis and trade-offs.
This approach solves the problem by breaking it down into smaller, overlapping subproblems using recursion. We define a function that calculates the length of the longest palindromic subsequence for a given substring. The solution explores all possibilities without storing intermediate results, leading to exponential time complexity.
Algorithm
- Define a recursive function
solve(s, i, j)that computes the length of the longest palindromic subsequence in the substrings[i...j]. - Base Cases:
- If
i > j(empty substring), return 0. - If
i == j(single character), return 1.
- If
- Recursive Step:
- If
s.charAt(i) == s.charAt(j), the characters at the ends match. They contribute 2 to the length. The rest of the palindrome is found in the inner substring. Return2 + solve(s, i + 1, j - 1). - If
s.charAt(i) != s.charAt(j), the end characters don't match. We must discard one of them. We find the maximum length by either excluding the start character (solve(s, i + 1, j)) or the end character (solve(s, i, j - 1)). Returnmax(solve(s, i + 1, j), solve(s, i, j - 1)).
- If
- The initial call is
solve(s, 0, s.length() - 1).
Walkthrough
We define a recursive function, say solve(s, i, j), which computes the length of the longest palindromic subsequence in the substring s[i...j]. The logic is as follows:
-
Base Cases:
- If the start index
iis greater than the end indexj, it means we have an empty substring, so we return 0. - If
iequalsj, we have a single-character substring, which is always a palindrome of length 1.
- If the start index
-
Recursive Step:
- If the characters at the ends of the substring,
s[i]ands[j], are the same, they can form the ends of a palindrome. The length will be 2 plus the length of the LPS in the inner substrings[i+1...j-1]. So, we return2 + solve(s, i + 1, j - 1). - If the characters
s[i]ands[j]are different, we cannot include both in the same palindrome. We have two choices:- Exclude
s[i]and find the LPS ins[i+1...j]. - Exclude
s[j]and find the LPS ins[i...j-1]. We take the maximum of these two possibilities:max(solve(s, i + 1, j), solve(s, i, j - 1)).
- Exclude
- If the characters at the ends of the substring,
The initial call to find the answer for the whole string s would be solve(s, 0, s.length() - 1). This method recomputes the same subproblems multiple times, making it highly inefficient.
class Solution { public int longestPalindromeSubseq(String s) { return solve(s, 0, s.length() - 1); } private int solve(String s, int i, int j) { // Base case 1: Empty substring if (i > j) { return 0; } // Base case 2: Single character substring if (i == j) { return 1; } // If characters at both ends match if (s.charAt(i) == s.charAt(j)) { return 2 + solve(s, i + 1, j - 1); } else { // If characters do not match return Math.max(solve(s, i + 1, j), solve(s, i, j - 1)); } }}Complexity
Time
O(2^n), where n is the length of the string. For each position where characters don't match, the function branches into two subproblems, leading to an exponential number of calls.
Space
O(n), where n is the length of the string. This space is used by the recursion stack. In the worst-case scenario, the recursion depth can go up to n.
Trade-offs
Pros
Simple to understand and implement.
Directly follows the problem's recursive definition.
Cons
Extremely inefficient due to a large number of redundant computations for the same subproblems.
Will result in a 'Time Limit Exceeded' (TLE) error on most platforms for non-trivial input sizes.
Solutions
Solution
class Solution { public int longestPalindromeSubseq ( String s ) { int n = s . length (); int [][] dp = new int [ n ][ n ]; for ( int i = 0 ; i < n ; ++ i ) { dp [ i ][ i ] = 1 ; } for ( int j = 1 ; j < n ; ++ j ) { for ( int i = j - 1 ; i >= 0 ; -- i ) { if ( s . charAt ( i ) == s . charAt ( j )) { dp [ i ][ j ] = dp [ i + 1 ][ j - 1 ] + 2 ; } else { dp [ i ][ j ] = Math . max ( dp [ i + 1 ][ j ], dp [ i ][ j - 1 ]); } } } return dp [ 0 ][ n - 1 ]; } }Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.