📌  相关文章
📜  满足给定条件的两个给定数组中相同索引子数组的最大长度(1)

📅  最后修改于: 2023-12-03 15:11:09.260000             🧑  作者: Mango

两个数组中相同索引子数组的最大长度

给定两个数组 arr1arr2,编写一个函数 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)$。