给两个整数数组 A 和 B ,返回两个数组中公共的、长度最长的子数组的长度。
示例 1:
输入: A: [1,2,3,2,1] B: [3,2,1,4,7] 输出: 3 解释: 长度最长的公共子数组是 [3, 2, 1]。说明:
1 <= len(A), len(B) <= 10000 <= A[i], B[i] < 100最暴力的方法就是枚举AB所有的子数组进行对比,这样的话,AB分别枚举所有子数组需要O(N ^ 2),那么总的时间复杂度需要O(N^4),肯定不可以。肯定是用动态规划来降低重复计算。
我们来找在哪里可以用到动态规划,对于重复的子数组,可以发现,**如果这两个数组的前面一个数相等,那么重复的长度就可以加1。**不需要比对后面的,因为已经相等了,我们的大致思想就是,找到重复的部分,然后往前扩展,如果新扩展的两个数相等,那么重复部分长度就增加了。
我们使用dp(i,j)来表示A[i:]和B[j:]两个子数组的相同的前缀的长度。
那么状态转移方程为: d p [ i ] [ j ] = { 0 i f A [ i ] ≠ B [ j ] d p [ i + 1 ] [ j + 1 ] + 1 i f A [ i ] = B [ j ] dp[i][j]= \begin{cases} 0&if&A[i]\ne B[j]\\ dp[i+1][j+1]+1&if&A[i]=B[j] \end{cases} dp[i][j]={0dp[i+1][j+1]+1ififA[i]=B[j]A[i]=B[j] 即,如果A[i]和B[j]相等,那么重复前缀的长度就在之前的基础上加一,如果不相等,那么就归零。
下面考虑边界条件,根据状态转移方程,dp(i,j)与右下角的dp有关,因此需要先将最后一行和最后一列的dp填写好。对于最后一行,就表示A[-1]和B中所有值是否相等,相等为1;对于最后一列,就是B[-1]和A中所有值是否相等,相等为1。
我们填写dp的同时维护一个变量保存dp数组中的最大值,最后返回这个最大值即为最长的重复数组长度。