516. 最长回文子序列
回文:正这读和反着读的意思是一样的一段话。
第一次尝试
第一次没有懂回文的意思,直接找的出现次数最多的字符。
class Solution {
public int longestPalindromeSubseq(String s) {
int res = 0;
Map<Character,Integer> map = new HashMap<>();
char[] cs = s.toCharArray();
for(char c:cs){
Integer in = map.get(c);
if(in!=null){
map.put(c,in+1);
}else{
map.put(c,1);
}
}
for(Integer entry:map.values()){
res = Math.max(res,entry.intValue());
}
return res;
}
}
动态规划
输入:s = "bbbab"
输出:4
可以删除某些字符
"aabaa"
输出:5
比如aabaa,aba也是回文字符串,那么可以从一个字符两边开始找。
再比如cbba,bb是回文字符串,最短的回文字符串长度为2,如果没有res = 1;
假设这一状态转移方程
dp/[i]/[j] 表示下标范围[i,j]内的最长回文字符串长度。
当s[i] = s[j] ,dp/[i]/[j] = dp/[i+1]/[j-1] + 2
当s[i] != s[j] ,dp[i]/[j] = max(dp[i+1]/[j],dp[i]/[j-1])
最终res = dp[0]/[n-1];
class Solution {
public int longestPalindromeSubseq(String s) {
int n = s.length();
int[][] dp = new int[n][n];
for (int i = n - 1; i >= 0; i--) {
dp[i][i] = 1;
char c1 = s.charAt(i);
for (int j = i + 1; j < n; j++) {
char c2 = s.charAt(j);
if (c1 == c2) {
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];
}
}
583. 两个字符串的删除操作
找最大的公共子序列
class Solution {
/**
找最大子序列的问题
aaaabbbcc
abbcc
动态规划
*/
public int minDistance(String word1, String word2) {
int len = word1.length();
int len2 = word2.length();
int[][] dp = new int[len+1][len2+1];
for(int i = 1;i<=len;i++){
char c1 = word1.charAt(i-1);
for(int j= 1;j<=len2;j++){
char c2 = word2.charAt(j-1);
if(c1==c2){
dp[i][j] = dp[i-1][j-1]+1;
}else{
dp[i][j] = Math.max(dp[i][j-1],dp[i-1][j]);
}
}
}
return len2+len-2*dp[len][len2];
}
}
- 最长定差子序列
https://leetcode-cn.com/problems/longest-arithmetic-subsequence-of-given-difference/
动态规划
class Solution {
/**
HashMap
*/
public int longestSubsequence(int[] arr, int difference) {
int res =0;
Map<Integer,Integer> dp = new HashMap<>();
for(int n:arr){
dp.put(n,dp.getOrDefault(n-difference,0)+1);
res = Math.max(res,dp.get(n));
}
return res;
}
}
最长递增子序列可以使用动态规划的思想 dp[0] 在数组位置0 他的最长递增子序列为1;
dp[0] = 1;