https://leetcode.com/problems/interleaving-string/
比较直观的dp了,可以当作一维DP的模板
二维DP数组
class Solution:
def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
if len(s1) + len(s2) != len(s3):
return False
dp = [[False for j in range(len(s2) + 1)] for i in range(len(s1) + 1)]
dp[0][0] = True
for i in range(0, len(s1) + 1):
for j in range(0, len(s2) + 1):
if i + j == 0:
continue
dp[i][j] = ((i > 0) and (s3[i + j - 1] == s1[i - 1]) and dp[i - 1][j]) or ((j > 0) and (s3[i + j - 1] == s2[j - 1]) and dp[i][j - 1])
return dp[len(s1)][len(s2)]
一维DP数组
class Solution:
def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
if len(s1) + len(s2) != len(s3):
return False
dp = [False for j in range(len(s2) + 1)]
dp[0] = True
for i in range(0, len(s1) + 1):
for j in range(0, len(s2) + 1):
if i + j == 0:
continue
dp[j] = (i > 0 and s3[i + j - 1] == s1[i - 1] and dp[j]) or (j > 0 and s3[i + j - 1] == s2[j - 1] and dp[j - 1])
return dp[len(s2)]
其实这种二维数字中,只用到上一行的,都可以转化成一维,转化起来也丝毫不费事,对比下两个代码就知道了。
延伸:72. Edit Distance
https://leetcode.com/problems/edit-distance/
遇到依赖前后状态的情况怎么办呢?
class Solution:
def minDistance(self, a: str, b: str) -> int:
dp = [[math.inf for j in range(len(b) + 1)] for i in range(len(a) + 1)]
for i in range(len(a) + 1):
dp[i][0] = i
for j in range(len(b) + 1):
dp[0][j] = j
for i in range(1, len(a) + 1):
for j in range(1, len(b) + 1):
if a[i - 1] == b[j - 1]:
dp[i][j] = dp[i - 1][j - 1]
else:
dp[i][j] = min(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1]) + 1
return dp[len(a)][len(b)]
其中dp[i][j - 1]
, dp[i - 1][j - 1]
新旧两个状态都用到了。
比较简单的方法是用两个数组存新旧两个状态,并不断更新。
一个trick的方式是,只用一个数字存旧状态,这样旧可以啦。
class Solution:
def minDistance(self, a: str, b: str) -> int:
dp = [math.inf for j in range(len(b) + 1)]
for j in range(len(b) + 1):
dp[j] = j # dp[0][j]
for i in range(1, len(a) + 1):
pre = dp[0] # dp[i - 1][0]
dp[0] = i # dp[i][0]
for j in range(1, len(b) + 1):
curr = dp[j] # dp[i - 1][j]
if a[i - 1] == b[j - 1]:
dp[j] = pre
else:
dp[j] = min(dp[j - 1], curr, pre) + 1
pre = curr # dp[i - 1][j - 1]
return dp[len(b)]