題目
給兩個整數數組 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)