LeetCode: 718.最长重复子数组

题目

给两个整数数组 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)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章