题目
给两个整数数组 A 和 B ,返回两个数组中公共的、长度最长的子数组的长度。
解法
滑窗法
首先想到的就是滑动法,就像卷积一样,其中一个序列从另一个数组的左边一直滑到右边,然后交叠部分挨个比较。
分三部分:1. 序列A逐渐全部走进序列B。2. 序列A完全在B中滑动。3.序列A逐渐离开B
class Solution:
def findLength(self, A: List[int], B: List[int]) -> int:
m = len(A)
n = len(B)
if m>n:
m, n, A, B = n, m, B, A
# A smaller, 默认是B在滑动,即长的序列参照A滑动
cnt = 0
for i in range(1, m+1): # 第一部分
cnt = max(cnt, self.count(A, 0, B, n-i, i))
for i in range(n-m-1, -1, -1): # 第二部分
cnt = max(cnt, self.count(A,0, B, i, m))
for i in range(1, m): # 第三部分
cnt = max(cnt, self.count(A, i, B, 0, m-i))
return cnt
def count(self, a, i, b, j, leng):
cnt = 0
max_cnt = 0
for k in range(leng):
if a[i+k] == b[j+k]:
cnt += 1
max_cnt = max(max_cnt, cnt)
else:
cnt = 0
return max_cnt
动态规划
dp[i][j] 代表以A[i] 和B[i]为起点的A[i:], B[i:],他们的最长公共子数组的数目。所以递归方程为
当A[i] == B[i],说明可以在dp[i+1][j+1]的基础上加1,代表以A[i]为起点的公共子树组的长度。如果不相等,则为0.
最后返回的就是dp的每一行的最大值的最大值。
class Solution:
def findLength(self, A: List[int], B: List[int]) -> int:
m = len(A)
n = len(B)
dp = [[0]*(n+1) for _ in range(1+m)]
for i in range(m-1, -1, -1):
for j in range(n-1, -1, -1):
if A[i] == B[j]:
dp[i][j] = dp[i+1][j+1] + 1
return max(max(row) for row in dp)