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 Falsedp = [[False for j in range(len(s2) + 1)] for i in range(len(s1) + 1)]dp[0][0] = Truefor i in range(0, len(s1) + 1):for j in range(0, len(s2) + 1):if i + j == 0:continuedp[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 Falsedp = [False for j in range(len(s2) + 1)]dp[0] = Truefor i in range(0, len(s1) + 1):for j in range(0, len(s2) + 1):if i + j == 0:continuedp[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] = ifor j in range(len(b) + 1):dp[0][j] = jfor 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]) + 1return 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] = preelse:dp[j] = min(dp[j - 1], curr, pre) + 1pre = curr # dp[i - 1][j - 1]return dp[len(b)]
