给两个整数数组 nums1
和 nums2
,返回 两个数组中 公共的 、长度最长的子数组的长度 。
示例 1:
输入:nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7]
输出:3
解释:长度最长的公共子数组是 [3,2,1] 。
题目。由题目可知,我们要求得是两个数组中间最长的相同的一部分,这里我还是首先想到的是暴力,推一下确实暴力也能够进行推出来。但是我们要进一步看能不能进行优化,根据最长长度,我们可以联想到是不是可以使用dp动态规划,答案是可以的。
1)二维dp推导。这里我们要推导,所以跟前一个状态有关,前一个状态是什么?那就是nums1[i - 1]和nums2[j - 1]相等,也就是前一个数是相等的,所以我们到当前这个数时就做长度+1操作。也就是dp[i]【j】=dp[i - 1]【j-1】+1。
2)或者第二种想法,就是按图形来分析。两个数组,一个为列,一个为行,所以就对应的话,这个对应的十字交点相等,那么值就是左上角值+1,也就是dp[i]【j】=dp[i - 1]【j-1】+1。
dp边界。由于第一个数可能会相等,所以左上角必须有值也就是i-1与j-1得,所以长度要比nums数组多1。
一维dp推导,由图像可知,后一行的数是前一行的数复制到下一行然后如果当前数前一个相等,就当前数为前面一个加1。也就是至于那一行的数有关,dp[j]=dp[j-1] + 1;
class Solution {public int findLength(int[] nums1, int[] nums2) {// 1.进行暴力遍历int max = 0;for (int i = 0; i < nums1.length; i++){int temp = 0;for (int j = 0; j < nums2.length; j++) {if (nums1[i] == nums2[j]){temp++;int k = i;int m = j;while(k + 1 < nums1.length && m + 1 < nums2.length && nums1[++k] == nums2[++m]){temp++;}max = Math.max(max, temp);temp = 0;}}}return max;// 2.二维dpint[][] dp = new int[nums1.length + 1][nums2.length + 1];int max = 0;for (int i = 1; i < nums1.length + 1; i++){for (int j = 1; j < nums2.length + 1; j++){if (nums1[i - 1] == nums2[j - 1]){dp[i][j] = dp[i - 1][j - 1] + 1;max = Math.max(max, dp[i][j]);}}}return max;// 3.一维dpint[] dp = new int[nums2.length + 1];int max = 0;for (int i = 1; i < nums1.length + 1; i++){for (int j = nums2.length; j > 0; j--){if (nums1[i - 1] == nums2[j - 1]){dp[j] = dp[j - 1] + 1;}else{// 每一次继承上一行的dp[j]值,如果相等,就会+1存max中,如果不相等,当前行刷新dp[j]值为0。dp[j] = 0;}max = max > dp[j] ? max : dp[j];}}return max;}
}
力扣题目练习:718. 最长重复子数组