题目:Input:
A: [1,2,3,2,1]
B: [3,2,1,4,7]
Output: 3
Explanation:
The repeated subarray with maximum length is [3, 2, 1].

思路:要找到两个数组中重复数据最长的子数组的长度。暴力枚举:每个A的下标i,分别与B的每个下标j作为起点,判断最长的重复数组长度。就像是移动两个指针。
例如i=0,j分别为0,1,2,3,4的时候,重复数组的长度分别为0,0,1,0,0。
当i=2,j=0的时候,重复数组的长度是3。接着还要计算i=2,j=1。如此一直计算到最后。这里的一个问题是当计算i=2,j=0找数组找到i=4,j=2结束之后,还有必要查找i=2,j=1位起始节点的子数组吗?有必要,在连续重复的数组中。例如数组A=[X,X,0,0,0,1],数组B=[0,0,0,0,1],可以看到以i=2,j=0,为起点,重复数组长度为3,;以i=2,j=1位起点,重复数组长度为4。所以这个暴力枚举没有可以省略操作的地方。
时间复杂度:A中每个元素都要和B中每个元素比较一次,O(m*n)

    public int findLength(int[] A, int[] B) {int len1 = A.length;int len2 = B.length;int maxLen = 0;for(int i=0;i<len1;i++){int j = 0;while(j<len2){if(A[i] == B[j]){int count = 0;int idxA = i;int idxB = j;while(idxA<len1 && idxB <len2 && A[idxA++] == B[idxB++]) count++;maxLen = Math.max(maxLen,count);}j++;}}return maxLen;}

学习:动态规划。上面分析是以数组的起点开始思考,动态规划以i,j作为子数组的终点元素,考虑从(0,0)到(i,j)中,重复数组的最长长度。
分析递归方程式。还以题目中的A、B数组为例。假设i=3,j=1,A[3]=B[1],那么dp[3][1] = dp[2][0]+1。假设i=3,j=4,A[3]≠B[4]A[3]≠B[4]A[3] \ne B[4],那么dp[3][4]=dp[2][3]。得出dp[i][j] = dp[i-1][j-1]+1 如果A[i]=B[j]。这里之所以dp[i][j]与dp[i-1][j-1]有关系,而不是跟dp[i][j-1]或者dp[i-1][j]有关系,是因为这是求重复数组的长度。而求重复数组肯定是两个数组的下标同时移动。
分析初始化条件。如果i=0,如果A[i]=B[j]则dp[0][j]=1否则为0。如果j=0,如果A[i]=B[j]则dp[i][0]=1否则为0。

    public int findLengthV2(int[] A, int[] B) {if (A == null || B == null)return 0;int m = A.length;int n = B.length;int[][] dp = new int[m][n];int maxLen = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (j == 0 || i == 0) {dp[i][j] = (A[i] == B[j] ? 1 : 0);} else if (A[i] == B[j]) {dp[i][j] = 1 + dp[i - 1][j - 1];maxLen = Math.max(maxLen, dp[i][j]);}}}return maxLen;}

思考:让我不能理解的地方是都是两层for循环,时间复杂度都是O(m*n)。方法二就比方法一快。相比较之下方式一多出了

while(idxA<len1 && idxB <len2 && A[idxA++] == B[idxB++]) count++;

这个步骤。方法二中只是简单的加法操作,当然更快。这样说来,方法一的时间复杂度就不是O(m*n)。当数组中重复元素多的情况下,两者速度相差就更大了。例如以下数组:
[59,59,59,93,59,59,59,59,59,59,59,59,59,59,59,59…]
[59,59,59,91,59,59,59,59,59,59,59,59,59,59,59,59..]
还有让我感觉神奇的地方是如果以(i,j)为子数组起点考虑问题,解决方法时间长;而以(i,j)为子数组终点考虑问题,竟然速度就快多了。这就是换个思路?再看看下面这段代码。

public int findLength(int[] a, int[] b) {int m = a.length, n = b.length;if (m == 0 || n == 0) return 0;int[][] dp = new int[m + 1][n + 1];int max = 0;for (int i = m - 1; i >= 0; i--)for (int j = n - 1; j >= 0; j--)max = Math.max(max, dp[i][j] = a[i] == b[j] ? 1 + dp[i + 1][j + 1] : 0);return max;        }

这个思路是以(i,j)作为子数组的开始节点,dp[i][j]存储以(i,j)为子数组起始节点的重复数组最长长度。这时候从最大的下标开始考虑。为什么从最大下标开始考虑,看下面的分析。
数组:A: [1,2,3,2,1] B: [3,2,1,4,7]
例如i=4,j=4,因为A[4]不等于B[4],所以dp[4][4]=0。
例如i=3,j=1,则dp[3][1]=dp[4][2]+1,应该是在以j=4,j=2这个数组重复数组最长长度+1,因为A[3]=B[1]。dp[3][1] 与dp[2][0]的关系就不是很确定。我可能因为向后移动了位置,重复数组变长,也可能变短。
开辟空间dp[m+1][n+1] ,而不是dp[m][n]是为了编码方便。
所以:暴力枚举与动态规划是两种思考问题的方式。动态规划在找递推关系的时候不是一定要有dp[i][j]与dp[i-1][j-1],也可能是dp[i+1][j+1]。根据题目的确定性关系确定递推式。

参考资料:
网页1
网页2

arry-718 Maximum Length of Repeated Subarray相关推荐

  1. leetcode 718. Maximum Length of Repeated Subarray | 718. 最长重复子数组(动态规划)

    题目 https://leetcode.com/problems/maximum-length-of-repeated-subarray/ 题解 Dynamic Programming [Accept ...

  2. 718. Maximum Length of Repeated Subarray 最长重复子数组

    Title 给两个整数数组 A 和 B ,返回两个数组中公共的.长度最长的子数组的长度. 示例 1: 输入: A: [1,2,3,2,1] B: [3,2,1,4,7] 输出: 3 **解释: ** ...

  3. 求两个数组的最长重复子数组 Maximum Length of Repeated Subarray

    为什么80%的码农都做不了架构师?>>>    问题: Given two integer arrays A and B, return the maximum length of ...

  4. Maximum length exceeded错误的解决办法

    一.问题 在序列化或反序列化对象时,由于对象数据量过大,超出了默认长度,引起程序抛出"maximum length exceeded"异常. 二.解决 在Web.config的&l ...

  5. oracle sqlldr 数据导入错误Field in data file exceeds maximum length解决

    使用oracle sqlldr进行数据导入时报Field in data file exceeds maximum length错误的解决办法: 一种是数据字段确实比数据库中的字段要长,这中错误需要调 ...

  6. java.lang.IllegalArgumentException: The maximum length of cell contents (text) is 32,767 characters

    问题描述: 在使用EasyExcel导出Excel的过程中出现了如下异常: IllegalArgumentException: The maximum length of cell contents ...

  7. oracle+exceeds,oracle 导入报错:field in data file exceeds maximum length

    今天用sqlldr导入数据时候报错: " Record 1: Rejected - Error on table ks_test, column khname. Field in data ...

  8. oracle sqlldr 数据导入时报错:Field in data file exceeds maximum length

    使用oracle sqlldr进行数据导入时报Field in data file exceeds maximum length错误: 在ctl文件中设置的数据长度小于实际数据长度 如: column ...

  9. oracle sqlldr 数据导入时报错:Field in data file exceeds maximum length完美解决

    使用oracle sqlldr进行数据导入时报Field in data file exceeds maximum length错误的解决办法: 一种是数据字段确实比数据库中的字段要长,这中错误需要调 ...

最新文章

  1. 今晚8点直播 | 详解基于百度自定义模板的OCR结果结构化处理技术
  2. JQuery UI库 - Dialog
  3. Exception经验之谈,万万没想到被很多团队采纳!
  4. C 盘FAT32变为 RAW 格式
  5. pygame两图层怎么搞_每天解决一个卖酒问题(176):小白怎么开拓市场?
  6. c语言volatile_[技术]为什么单片机C语言编程时某一变量有时乱码
  7. 一文详解「队列」,手撸队列的3种方法!
  8. java线程等待_java 中线程等待与通知的实现
  9. Spring4.x(7)---对象的生命周期方法
  10. 我不是bug神(JVM问题排查)
  11. ubuntu 15.10 升级 到Ubuntu 16.04.3 LTS
  12. ZYNQ PL开发流程
  13. python万年历代码_利用python实现万年历
  14. html5二维动画教程,Flash二维动画制作案例教程
  15. 【谷粒商城】【认证服务】验证码、社交登录、分布式session、单点登录
  16. 市场调查大赛全保姆教程(经验分享)
  17. 2020年中国电子商务服务行业现状及发展趋势分析,行业集中度将不断提升「图」
  18. DNT精英论坛(暨.NET北京俱乐部)第2期:.NET依赖注入在区块链项目AElf中的实践
  19. TQ210 —— LCD
  20. 医院管理系统明细 HIS源码

热门文章

  1. Tomcat 配置 login 和 gas
  2. FusionChart完全入门手册8
  3. Android 友盟推送开发
  4. Android 支付宝登录
  5. Android studio 运行即打包keystore之build.gradle设置
  6. java 常用流_Java流类图结构: 流的概念和作用流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数...
  7. java socket 浏览器_Socket实现Java和浏览器交互。
  8. 基于Linux系统的手机,中国最新超算操作系统揭秘:基于Linux
  9. pytorch之with torch.no_grad
  10. 修改无效_解决docker部署gitlab时,clone地址无效和修改默认端口