最长递归子序列
题目
给定数组arr,返回arr中的最长递增子序列,如arr=[2,1,5,3,6,4,8,9,7]
,返回的最长递增子序列为[1,3,4,8,9]
题解思路
先用DP来求解子序列递增的最大长度,如arr的长度序列为dp=[1,1,2,2,3,3,4,5,4]
,然后对这个长度序列dp从右到左遍历,得到最长递增子序列。
-
求解长度序列,令dp[i]表示在以arr[i]这个数结尾的情况下,arr[0…i]中的最大递增子序列的长度。
则状态转移方程为:dp[i]=max{dp[j]+1(0<=j<i,arr[j]<arr[i])}
-
然后遍历dp数组,从右向左,如dp=[1,1,2,2,3,3,4,5,4]
,先找到最大值为5,索引为7,即’9’,前一个数则应该是4,索引为6,即’8’;重复该步骤即可;
该方法时间复杂度为O(N^2)
如果在求解dp数组的过程中采用二分查找来进行优化,可以将复杂度降低到O(N*logN)
最长公共子串
题目
给定两个字符串str1和str2,返回两个字符串的最长公共字串,如str1=’1AB2345CD’,str2=’12345EF’,返回’2345’
解题思路
经典的动态规划方法的时间复杂度为O(M*N)
,空间复杂度为O(M*N)
,采用压缩优化后,可将空间复杂度优化至O(1)
dp[i][j]表示将str1[i]和str2[j]作为公共字串的最后一个字符,公共字串的长度。则:
状态转移方程为:dp[i+1,j+1]=(str1[i]==str2[j])?dp[i,j]+1:0;
优化思路:因为计算每个dp[i][j]时只用到了其左上方的dp[i-1][j-1],所以只需要一个变量即可,即空间复杂度为O(1)
最长公共子序列
题目
给定两个字符串str1和str2,返回两个字符串的最长公共子序列
思路
状态转移方式:
c[i][j]记录str1[i]与str2[j] 的LCS 的长度
编辑距离
题目
传送leetcode Edit Distance
解题思路:
设状态为 f[i][j],表示 A[0,i] 和 B[0,j] 之间的最小编辑距离。设 A[0,i] 的形式是 str1c,B[0,j] 的形式是 str2d,
- 如果 c==d,则 f[i][j]=f[i-1][j-1];
- 如果 c!=d,
- 如果将 c 替换成 d,则 f[i][j]=f[i-1][j-1]+1;
- 如果在 c 后面添加一个 d,则 f[i][j]=f[i][j-1]+1;
- 如果将 c 删除,则 f[i][j]=f[i-1][j]+1;
字符串的交错组成
题目
给定三个字符串s1,s2,s3,判断s3是否由s1和s2交错组成。leetcode题目:Interleaving String
分析
设状态 f[i][j],表示 s1[0,i] 和 s2[0,j],匹配 s3[0, i+j]。如果 s1 的最后一个字符等
于 s3 的最后一个字符,则 f[i][j]=f[i-1][j]
;如果 s2 的最后一个字符等于 s3 的最后一个字符,则 f[i][j]=f[i][j-1]。
因此状态转移方程如下:
f[i][j] = (s1[i - 1] == s3 [i + j - 1] && f[i - 1][j]) || (s2[j - 1] == s3 [i + j - 1] && f[i][j - 1]);
二维DP,时间复杂度 O(n^2),空间复杂度 O(n^2) ,另外可以用滚动数组进行空间复杂度优化,O(N)