作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/
题目地址:https://leetcode.com/problems/longest-palindromic-subsequence/description/
题目描述
Given a string s, find the longest palindromic subsequence’s length in s. You may assume that the maximum length of s is 1000.
Example 1:
Input:
"bbbab"
Output:
4
One possible longest palindromic subsequence is "bbbb".
Example 2:
Input:
"cbbd"
Output:
2
One possible longest palindromic subsequence is "bb".
题目大意
找出一个字符串中最长的回文序列的长度。注意序列可以是不连续的,而子字符串是连续的。
解题方法
动态规划。
遇到一个数组,如果求其最大、最小、最长、最短的个数,而不需要知道具体解的问题,一般考虑动态规划。
我们在考虑动态规划的转移方程的时候,一定切记,转移方程右边部分(子问题)认为是满足题设条件的。
当已知一个序列是回文时,添加首尾元素后的序列存在两种情况,一种是首尾元素相等,则最长回文的长度加2,当首尾元素不相等,则最长回文序列为仅添加首元素时的最长回文与仅添加尾元素时的最长回文之间的最大值。我们可以用dp[i][j]表示s[i…j]中的最长回文序列,而状态转移方程则是
1. i > j,dp[i][j] = 0;
2. i == j,dp[i][j] = 1;
3. i < j且s[i] == s[j],dp[i][j] = dp[i + 1][j - 1] + 2;
4. i < j且s[i]!= s[j],dp[i][j] = max(dp[i + 1][j],dp[i][j - 1]);
从状态转移方程可以看出,计算dp[i][j]时需要用到dp[i+1][j - 1]和dp[i + 1][j],所以对于i的遍历应该从尾部开始,最后返回dp[0][s.length() - 1]就行。
为什么用java写?因为python超时了!!
class Solution {
public int longestPalindromeSubseq(String s) {
int size = s.length();
int[][] dp = new int[size][size];
for(int i = size - 1; i >= 0; i--){
dp[i][i] = 1;
for(int j = i + 1; j < size; j++){
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][size - 1];
}
}
超时的python代码:
class Solution:
def longestPalindromeSubseq(self, s):
"""
:type s: str
:rtype: int
"""
n = len(s)
dp = [[0] * n for _ in range(n)]
for i in range(n - 1, -1, -1):
dp[i][i] = 1
for j in range(i + 1, n):
if s[i] == s[j]:
dp[i][j] = dp[i + 1][j - 1] + 2
else:
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
return dp[0][n - 1]
日期
2018 年 3 月 15 日 --雾霾消散,春光明媚