这个题解使用了二分查找和滚动哈希的思路。首先定义了一个 check 函数,用于判断是否存在长度为 length 的公共子数组。check 函数中,分别计算 nums1 和 nums2 的长度为 length 的子数组的哈希值,并使用滚动哈希的方法快速计算出所有可能的子数组哈希值,然后判断是否存在相同的哈希值,如果存在则说明存在长度为 length 的公共子数组。接下来使用二分查找的方法,初始化 left 为 0,right 为 min(len(nums1), len(nums2)),然后进行二分查找,如果 check(mid) 为 True,说明存在长度为 mid 的公共子数组,则将 ans 更新为 mid,并将 left 更新为 mid + 1,否则将 right 更新为 mid - 1。最终返回 ans 即为最长重复子数组的长度。
时间复杂度: O((n + m) * log(min(n, m)))
空间复杂度: O(n)
class Solution:
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
base, mod = 131, 10**9 + 9
def check(length: int) -> bool:
hashA = 0
for i in range(length):
hashA = (hashA * base + nums1[i]) % mod
bucketA = {hashA}
mult = pow(base, length - 1, mod)
for i in range(length, len(nums1)):
hashA = ((hashA - nums1[i - length] * mult) * base + nums1[i]) % mod
bucketA.add(hashA)
hashB = 0
for i in range(length):
hashB = (hashB * base + nums2[i]) % mod
if hashB in bucketA:
return True
for i in range(length, len(nums2)):
hashB = ((hashB - nums2[i - length] * mult) * base + nums2[i]) % mod
if hashB in bucketA:
return True
return False
left, right = 0, min(len(nums1), len(nums2))
ans = 0
while left <= right:
mid = (left + right) // 2
if check(mid):
ans = mid
left = mid + 1
else:
right = mid - 1
return ans