718. 最长重复子数组 - 力扣(LeetCode) 知识点 最长公共子串 动态规划
dp[i][j]表示第一个数组以a[i]为结尾和第二个数组以b[j]为结尾的最大公共子串(要求是a[i]==b[j]=x,即以x结尾的串) dp公式:if(a[i]==b[j]) dp[i+1][j+1] = dp[i-1][j-1]+1 然后max不断更新即可
public int findLength(int[] nums1, int[] nums2) {
// int[][] dp = new int[nums1.length+1][nums2.length+1]; //dp[i][j]表示nums1[i]为结尾的串和nums2[j]为结尾的串的最大公共子串
// int max = 0;
// for(int i = 0; i < nums1.length; i++) {
// for(int j = 0; j < nums2.length; j++) {
// if(nums1[i] == nums2[j]) {
// dp[i+1][j+1] = dp[i][j]+1;
// max = Math.max(max,dp[i+1][j+1]);
// }
// }
// }
//一维做法,由于每次的更新都是只用到二维数组当前位置的左上角那个数据,所以我们纵向那一维可以通过横向遍历顺序的改变而省略纵向维度,之前的数据能够利用到
int[] dp = new int[nums2.length+1];
int max = 0;
for(int i = 0; i < nums1.length; i++) {
for(int j = nums2.length-1; j >=0 ; j--) {
if(nums1[i] == nums2[j]) {
dp[j+1] = dp[j]+1;
max = Math.max(max,dp[j+1]);
}
else dp[j+1] = 0;//记得要加这一步,相当于dp[i+1][j+1] =0,不然dp[i+1][j+1]会保留上一轮的dp[j+1]的值,造成错误
}
}
return max;
}
}
空间优化: 二维转一维 原因如下
由于每次的更新都是只用到二维数组当前位置的左上角那个数据,所以我们纵向那一维可以通过改变横向遍历顺序进而能够实现省略纵向空间维度
(图片来源:leetcode718题目的高赞题解中的"笨猪爆破组"作者)