718. 最长重复子数组
题目链接:
给两个整数数组 nums1
和 nums2
,返回 两个数组中 公共的 、长度最长的子数组的长度 。
示例 1:
输入:nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7]
输出:3
解释:长度最长的公共子数组是 [3,2,1] 。
示例 2:
输入:nums1 = [0,0,0,0,0], nums2 = [0,0,0,0,0]
输出:5
提示:
-
1 <= nums1.length, nums2.length <= 1000
-
0 <= nums1[i], nums2[i] <= 100
解题思路
题目中说的子数组,其实就是连续子序列。运用动态规划来解答。
C++
class Solution { public: int findLength(vector<int>& nums1, vector<int>& nums2) { // 1. dp数组的含义 // dp[i][j] :以下标i - 1为结尾的 nums1,和以下标j - 1为结尾的 nums2,最长重复子数组长度为dp[i][j] // 注意:在遍历dp[i][j]的时候i 和 j都要从1开始的,这就减轻了初始化dp数组的工作 // 2. 初始化 // 根据dp[i][j]的定义,dp[i][0] 和dp[0][j]其实都是没有意义的!它们是为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1; // 所以dp[i][0] 和dp[0][j]初始化为0。 vector<vector<int>> dp(nums1.size() + 1, vector<int>(nums2.size() + 1, 0)); int result = 0; // 记录dp[i][j]的最大值 // 4. 遍历顺序:外层for循环遍历 nums1,内层for循环遍历 nums2。 for (int i = 1; i <= nums1.size(); i++) { for (int j = 1; j <= nums2.size(); j++) { if (nums1[i - 1] == nums2[j - 1]) { // 2.递推公式 // 根据dp[i][j]的定义,dp[i][j]的状态只能由dp[i - 1][j - 1]推导出来。 // 即当nums1[i - 1] 和 nums2[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1; dp[i][j] = dp[i - 1][j - 1] + 1; } result = dp[i][j] > result ? dp[i][j] : result; } } return result; } };
JavaScript
/** * @param {number[]} nums1 * @param {number[]} nums2 * @return {number} */ var findLength = function(nums1, nums2) { const dp = Array(nums1.length + 1).fill().map(item => Array(nums2.length + 1).fill(0)); let result; for (let i = 1; i <= nums1.length; i++) { for (let j = 1; j <= nums2.length; j++) { if (nums1[i - 1] === nums2[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } result = result > dp[i][j] ? result : dp[i][j]; } } return result; };
-
时间复杂度:O(n × m),n 为nums1长度,m为muns2长度
-