解决两个字符串的动态规划问题,一般都是用两个指针 i,j
分别指向两个字符串的最后,然后一步步往前走,缩小问题的规模。
1.递归
base case 是 i
走完 s1
或 j
走完 s2
,可以直接返回另一个字符串剩下的长度。
对于每对字符 s1[i]
和 s2[j]
,可以有四种操作:
1 | if s1[i] == s2[j]: |
⏬⏬⏬
1 | public int minDistance(String word1, String word2) { |
这段代码有点小问题就是,这个解法是暴力解法,存在重叠子问题,需要用动态规划技巧来优化。
对于子问题 dp(i-1, j-1)
,如何通过原问题 dp(i, j)
得到呢?有不止一条路径,比如 dp(i, j) -> #1
和 dp(i, j) -> #2 -> #3
。一旦发现一条重复路径,就说明存在巨量重复路径,也就是重叠子问题。
2.动态规划优化
常用就是用HashMap
来做备忘录,避免重叠路径:
1 | HashMap<String, Integer> map = new HashMap<>(); |
或是用dp
数组:
dp[..][0]
和 dp[0][..]
对应 base case,dp[i][j]
的含义和之前的 dp 函数类似:
1 | int dp(i, j) |
dp 函数的 base case 是 i,j
等于 -1,而数组索引至少是 0,所以 dp 数组会偏移一位。
既然 dp 数组和递归 dp 函数含义一样,也就可以直接套用之前的思路写代码,唯一不同的是,DP table 是自底向上求解,递归解法是自顶向下求解:
1 | int minDistance(String s1, String s2) { |