首页 > 其他分享 >【DP】LeetCode 718. 最长重复子数组

【DP】LeetCode 718. 最长重复子数组

时间:2023-04-22 09:48:50浏览次数:46  
标签:最长 718 int 重复子 nums1 dp 数组 LeetCode nums2

题目链接

718. 最长重复子数组

思路

分析动态规划题目的时候只需要考虑最后一个阶段,因为所有的阶段转化都是相同的,考虑最后一个阶段容易发现规律

在数组的动态规划问题中,一般 dp[i] 都是表示以 nums 以第 i 个元素组成(即 nums[i - 1])的状态;dp[i][j] 分别表示以 nums1 前 i 个元素(即 nums1[i - 1])组成和以 nums2 前 j 个元素(即 nums2[j - 1])组成的状态,以此类推

字符串也是个数组,是字符数组

表示状态

状态表示就是靠猜,但是会有猜的套路,一般都是通过最终结果和数组数量来猜

看到题目有两个数组,根据上文,我们很容易想到使用 \(dp[i][j]\) 表示以 nums1 前 i 个元素和 nums2 前 j 个元素 组成的最长公共子数组长度

找状态转移方程

思考的方向是:大问题的最优解怎么由小问题的最优解得到

我们要求 \(dp[i][j]\),那么我们就需要想想它怎么和之前的 \(dp\) 元素联系起来。

最容易想到的一点是:如果 \(nums1[i - 1] = nums2[j - 1]\),那么相当于在 \(dp[i - 1][j - 1]\) 的基础上再 +1,即

\[dp[i][j] = dp[i - 1][j - 1] + 1, \ nums1[i - 1] = nums2[j - 1] \]

那如果不相等呢?我们仔细想一想:在这个问题中,我们求的最长子数组长度,实际上是遍历过程中最长公共后缀的长度

比如在样例中:

\[nums1 = [1, 2, 3, 2, 1], \ nums2 = [3, 2, 1, 4, 7] \]

它的最长公共部分 \([3, 2, 1]\) 实际上是 \([1, 2, 3, 2, 1], \ [3, 2, 1]\) 的两个后缀

也就是说在我们遍历整个 \(dp\) 数组的过程中,我们只需要对有公共后缀的部分(即 \(nums1[i - 1] = nums2[j - 1]\) 部分)操作

这样我们就得出了最终的状态转移方程:

\[dp[i][j] = \left\{ \begin{aligned} & dp[i - 1][j - 1] + 1, & nums1[i - 1] = nums2[j - 1], \\ & nothing, & nums1[i - 1] \neq nums2[j - 1]. \end{aligned} \right. \]

边界处理

将 \(dp\) 数组初始化为0即可

空间优化

代码

dp数组版

class Solution {
    public int findLength(int[] nums1, int[] nums2) {
        int n1 = nums1.length;
        int n2 = nums2.length;
        int[][] dp = new int[n1 + 1][n2 + 1];
        int result = 0;

        for(int i = 1; i <= n1; i++){
            for(int j = 1; j <= n2; j++){
                if(nums1[i - 1] == nums2[j - 1]){
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                    result = Math.max(result, dp[i][j]);
                }
            }
        }

        return result;
    }
}

空间优化版


标签:最长,718,int,重复子,nums1,dp,数组,LeetCode,nums2
From: https://www.cnblogs.com/shixuanliu/p/17342455.html

相关文章

  • #yyds干货盘点# LeetCode程序员面试金典:最长有效括号
    题目:给你一个只包含'(' 和')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。 示例1:输入:s="(()"输出:2解释:最长有效括号子串是"()"示例2:输入:s=")()())"输出:4解释:最长有效括号子串是"()()"示例3:输入:s=""输出:0代码实现:classSolution{publicint......
  • #yyds干货盘点# LeetCode面试题:删除排序链表中的重复元素
    1.简述:给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回已排序的链表 。 示例1:输入:head=[1,1,2]输出:[1,2]示例2:输入:head=[1,1,2,3,3]输出:[1,2,3]2.代码实现:classSolution{publicListNodedeleteDuplicates(ListNodehead){......
  • day52 300.最长递增子序列 | 674. 最长连续递增序列 | 718. 最长重复子数组
    给你一个整数数组nums,找到其中最长严格递增子序列的长度。子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]是数组[0,3,1,6,2,2,7]的子序列。示例1:输入:nums=[10,9,2,5,3,7,101,18]输出:4解释:最长递增子序列是[2,3,7,101......
  • 【LeetCode动态规划#11】打家劫舍系列题(涉及环结构和树形DP的讨论)
    打家劫舍力扣题目链接(opensnewwindow)你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组......
  • 【总结】浅刷leetcode,对于位运算提高性能的一些总结
    目录什么是位运算?位运算技巧1.判断奇偶性2.交换两个数3.判断一个数是否是2的幂次方4.取绝对值5.计算平均数结论位运算技巧是计算机科学中非常重要的一部分,它可以用来解决很多实际问题。在本篇博客中,我们将介绍一些常见的位运算技巧,以及它们在实际应用中的使用。什......
  • leetcode_打卡10
    leetcode_打卡10题目:283.移动零思路:双指针,数值互相交换,不是复制覆盖代码:classSolution{publicvoidmoveZeroes(int[]nums){intn=nums.length;intl=0,r=0;while(r<n){if(nums[r]!=0){swap(nums,l,r);......
  • leetcode_打卡09
    leetcode_打卡09题目:443.压缩字符串思路:双指针代码:classSolution{publicintcompress(char[]chars){intn=chars.length;intwrite=0,left=0;for(intread=0;read<n;read++){if(read==n-1||chars[r......
  • 【DP】LeetCode 312. 戳气球
    题目链接312.戳气球思路参考动态规划套路解决戳气球问题分析动态规划题目的时候只需要考虑最后一个阶段,因为所有的阶段转化都是相同的,考虑最后一个阶段容易发现规律在数组的动态规划问题中,一般dp[i]都是表示以nums[i]为结尾的状态;dp[i][j]分别表示以nums1[i]和nums......
  • leetcode-876链表的中间节点
    找链表的中间节点思路心得当不知道while的终止条件时,可以先写while(true),然后在循环体中写终止条件,这样写的好处是可以暂时不考虑终止条件,使思路更清晰;坏处是这样有时候会使循环体的内容很混乱要注意分类!本题中把情况分为节点个数是奇数和偶数去分析,最终找到统一的......
  • leetcode-234回文链表
    回文链表方法一:借助数组进行判断把节点的值复制到一个数组中再利用数组进行判断,但是这样需要占用额外的空间/***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode():val(0),next(nullptr){}*......