经典dp--股票买卖系列之Go写法
-
- [Edit Distance](https://leetcode.com/problems/edit-distance/)
- [Longest Common Subsequence](https://leetcode.com/problems/longest-common-subsequence/)
- [剑指 Offer 19. 正则表达式匹配](https://leetcode-cn.com/problems/zheng-ze-biao-da-shi-pi-pei-lcof/)
- [44. 通配符匹配](https://leetcode-cn.com/problems/wildcard-matching/)
在这里我目前碰到了一些比较像的字符串dp处理的问题,这些问题结构很相似,都是借助二维数组来保存状态,根据某种状态来转移更新。其中第一和二道题很类似,三和四类似
PS:画个矩阵出来比一比更加形象生动!!!
Edit Distance
编辑距离这道题连接和题目描述见原链接(标题)
首先,我们定义一个dp
数组,大小为m = len(word1), n = len(word2)
。dp[i][j]的含义表示子串word1[0:i]
和word2[0:j]
的最小编辑距离。
然后,我们可知操作主要有四种,也就是插入、删除、替换和什么都不搞,这四种操作我们可以看做获得最优解的一个状态,也就是说我们当前状态是通过这四种操作而获得。
所以我们有情况,当word1[i] == word2[j]
时,dp[i][j]= dp[i-1][j-1]
, 因为两个相等了,就不需要操作了;当word1[i] != word2[j]
时, 这是我们有三种操作可以选择,当然,我们求最小编辑距离,就是从三种操作中选择最小的那个:min(dp[i-1][j], dp[i][j-1],dp[i-1][j-1]) + 1
在这里特别说明一下dp[i
][j-1]表示对word1
进行插入,dp[i-1][j]
表示对word1
进行删除,dp[i-1][j-1]
表示对word1
进行替换
最后,我们需要明确一下边界,也就是初始值,我们需要对dp
数组进行初始化,也就是dp
数组大小是(m+1) x (n+1)
的,初始化的值为对应的长度。举个简单的例子就是,假定word2
长度为0
,对于子串word1[0:i]
对应的初始值dp[0][i] = i
, 因为这个匹配是要不断删除word1
字母,同理dp[i][0] = i
func minDistance(word1 string, word2 string) int {
len1 := len(word1)
len2 := len(word2)
dp := make([][]int, len1+1)
for i:=0; i<=len1; i++ {
dp[i] = make([]int, len2+1)
}
// init 边界
for i:=1; i<=len2; i++ {
dp[0][i] = i
}
for i:=1; i<=len1; i++ {
dp[i][0] = i
}
// finish init
for i:=1; i<=len1; i++ {
for j:=1; j<=len2;j++ {
// 根据状态转移方程计算dp[i][j]
if word1[i-1] == word2[j-1] {
dp[i][j] = dp[i-1][j-1]
} else {
dp[i][j] = minValues(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]) + 1
}
}
}
return dp[len1][len2]
}
func minValues(values ...int)