📅  最后修改于: 2023-12-03 15:11:09.260000             🧑  作者: Mango
给定两个数组 arr1
和 arr2
,编写一个函数 findLength
,返回两个数组中相同索引位置的子数组的最大长度。
例如:
输入:arr1 = [1,2,3,2,1], arr2 = [3,2,1,4,7]
输出:3
解释:子数组 [3,2,1] 是两个数组中的最长相同子数组,长度为 3。
对于两个数组,枚举其中一个数组的所有子数组,再在另一个数组中寻找相同的子数组,通过判断子数组是否相同得到最长的相同子数组的长度。
代码如下:
class Solution:
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
n = len(nums1)
m = len(nums2)
res = 0
for i in range(n):
for j in range(m):
k = 0
while (i+k<n and j+k<m and nums1[i+k] == nums2[j+k]):
k += 1
res = max(res, k)
return res
时间复杂度为 $O(n^3)$,提交后会发现TLE(Time Limit Exceeded),不过可以通过一部分测试案例。
滑动窗口算法是一种用于字符串和数组相关问题的优秀算法,通过维护一个窗口,在其中寻找最长的符合条件的连续子数组。
对于本题,我们可以从数组的第一个位置开始比较,比较窗口和另一个数组的子数组是否相同,再将窗口向右滑动。
代码如下:
class Solution:
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
n = len(nums1)
m = len(nums2)
res = 0
for i in range(n):
k = 0
for j in range(m):
if i+k<n and j+k<m and nums1[i+k] == nums2[j+k]:
k += 1
res = max(res, k)
return res
时间复杂度为 $O(n^2)$,通过所有测试案例。
动态规划算法思路:类似滑动窗口,找到重复子问题并通过存储结果来避免重复计算,最终找到最优解。
对于本题,我们定义 $dp[i][j]$ 表示以第一个数组的第i个元素和第二个数组的第j个元素结尾的相同子数组的长度。只有当 $nums1[i] = nums2[j]$ 时,我们才能继续向前扩展子数组。
代码如下:
class Solution:
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
n = len(nums1)
m = len(nums2)
res = 0
dp = [[0]*(m+1) for _ in range(n+1)]
for i in range(1, n+1):
for j in range(1, m+1):
if nums1[i-1] == nums2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
res = max(res, dp[i][j])
return res
时间复杂度为 $O(nm)$,通过所有测试案例。
三种方法,时间复杂度依次解决了TLE问题,并通过了测试案例。
笨办法:暴力枚举;
滑动窗口:时间复杂度为 $O(n^2)$;
动态规划:时间复杂度为 $O(nm)$。