一般涉及到子序列的最值问题,可采用动态规划进行求解。
当只有一个字符串或者一个数组情况下,dp表通常表示为:
dp[i]: 0-i的最长序列
dp[i][j]:i-j的最长序列
当有两个字符串或者数组时,dp表通常表示为:
dp[i][j]:字符串1:0-i 字符串2:0-j间的最长序列
时间复杂度一般在O(N^2)
基本框架:
#初始化dp表
dp[0][0][...] = base
#进行状态转移
for 状态1 in 状态1的所有取值:
for 状态2 in 状态2的所有取值:
for...
dp[状态1][状态2][...] = 求最值(选择1,选择2...)
最长重复子数组
给两个整数数组 A 和 B ,返回两个数组中公共的、长度最长的子数组的长度。
输入:
A: [1,2,3,2,1]
B: [3,2,1,4,7]
输出: 3
解释:
长度最长的公共子数组是 [3, 2, 1]。
if A[i] = A[j]:
dp[i][j] = dp[i-1][j-1]+1
public int findLength(int[] A, int[] B) {
//dp[i][j]表示A(0-i)B(0-j)的最长子数组
int[][] dp = new int[A.length+1][B.length+1];
//初始化dp表
for(int i = 0;i < dp.length;i++){
Arrays.fill(dp[i],0);
}
int res = 0;
for (int i = 1;i < dp.length;i++){
for (int j = 1;j < B.length+1;j++){
if (A[i-1] == B[j-1]){
dp[i][j] = dp[i-1][j-1]+1;
}
res = Math.max(res,dp[i][j]);
}
}
return res;
}
最长公共子序列
if(text1.charAt(i-1) == text2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
//比如"bl"与"yby"
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
public int longestCommonSubsequence(String text1, String text2) {
int[][] dp = new int [text1.length()+1][text2.length()+1];
//初始化dp表
for (int i = 0;i < dp.length; i++){
dp[i][0] = 0;
}
for (int i = 0; i < dp[0].length;i++){
dp[0][i] = 0;
}
for (int i = 1;i < dp.length; i++){
for (int j = 1;j < dp[0].length;j++){
if(text1.charAt(i-1) == text2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
//比如"bl"与"yby"
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[text1.length()][text2.length()];
}