0044.通配符匹配
方法一:回溯 + 记忆化搜索
暴力搜索,不过可以通过数组进行优化,时间复杂度 $O(m^n)$,空间复杂度 $O(m \times n)$。
func isMatch(s string, p string) bool {
// 1表示匹配, 2表示不匹配
memo, m, n := make([][]int, len(s)+10), len(s), len(p)
for i := 0; i < m+10; i++ {
memo[i] = make([]int, n+10)
}
var backtrack func(p1, p2 int) bool
backtrack = func(p1, p2 int) bool {
if memo[p1][p2] != 0 {
return memo[p1][p2] == 1
}
if p2 >= n {
if p1 >= m {
memo[p1][p2] = 1
} else {
memo[p1][p2] = 2
}
return memo[p1][p2] == 1
}
ans := false
if p1 <= m && p[p2] == '*' {
ans = backtrack(p1, p2+1) || backtrack(p1+1, p2)
}
if p1 < m && p[p2] == '?' {
ans = backtrack(p1+1, p2+1)
} else if p1 < m && s[p1] == p[p2] {
ans = backtrack(p1+1, p2+1)
}
memo[p1][p2] = 2
if ans {
memo[p1][p2] = 1
}
return ans
}
return backtrack(0, 0)
}
方法二:动态规划
时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。
func isMatch(s string, p string) bool {
dp, m, n := make([][]bool, 0), len(s), len(p)
for i := 0; i <= m; i++ {
dp = append(dp, make([]bool, n+1))
}
dp[0][0] = true
for i := 1; i <= n; i++ {
if p[i-1] == '*' {
dp[0][i] = true
} else {
break
}
}
for i := 1; i <= m; i++ {
for j := 1; j <= n; j++ {
if s[i-1] == p[j-1] || p[j-1] == '?' {
dp[i][j] = dp[i-1][j-1]
} else if p[j-1] == '*' {
dp[i][j] = dp[i][j-1] || dp[i-1][j]
}
}
}
return dp[m][n]
}