题目: 最长公共子序列
给定两个字符串 text1
和 text2
,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0
。
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,"ace"
是 "abcde"
的子序列,但 "aec"
不是 "abcde"
的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。
示例 1:
1 | 输入:text1 = "abcde", text2 = "ace" |
示例 2:
1 | 输入:text1 = "abc", text2 = "abc" |
示例 3:
1 | 输入:text1 = "abc", text2 = "def" |
提示:
1 <= text1.length, text2.length <= 1000
text1 和 text2 仅由小写英文字符组成。
分析:
定义 dp[i][j]
表示 text1[0:i]
和 text2[0:j]
的最长公共子序列,其中 text1[0:i]
表示数组中从0
到i
长度为 i + 1
的子数组
当 text1[i - 1] == text2[j - 1]
时,说明两个子字符串的最后一位相等,所以最长公共子序列又增加了 1
,所以 dp[i][j] = dp[i - 1][j - 1] + 1
;举个例子,比如对于 ac
和 bc
而言,他们的最长公共子序列的长度等于 a
和 b
的最长公共子序列长度 0 + 1 = 1
。
当 text1[i - 1] != text2[j - 1]
时,说明两个子字符串的最后一位不相等,那么此时的状态 dp[i][j]
应该是 dp[i - 1][j]
和 dp[i][j - 1]
的最大值。举个例子,比如对于 ace
和 bc
而言,他们的最长公共子序列的长度等于 ① ace
和 b
的最长公共子序列长度0
与 ② ac
和 bc
的最长公共子序列长度1
的最大值,即 1
。
综上状态转移方程为:
dp[i][j] = dp[i - 1][j - 1] + 1, 当 text1[i - 1] == text2[j - 1];text1[i−1]==text2[j−1];
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]), 当 text1[i - 1] != text2[j - 1]text1[i−1]!=text2[j−1]
题解:
1 | class Solution { |
总结:
遇到考查动态规划的题也算有点头绪了,我的感悟是这是一种从无到有的思想:一步一步将单个信息纳入考虑范围,然后按照条件更新已知的情报。其中的难点在于dp
数组的定义,怎么样的定义才能有效快捷地达成目的呢?