718.最长重复子数组

暴力题解

  • 时间复杂度O(n^3),超时

代码

public  int findLength(int[] A, int[] B) {
    int max=0;
    int l1=A.length,l2=B.length;
    for(int i=0;i<l1;i++){
        int tmp=0;
        for(int j=0;j<l2;j++){
            if(A[i]==B[j]){
                tmp=find(i,j,A,B);
            }
            max=Math.max(max,tmp);
        }

    }
    return max;
}

public int find(int i,int j,int[] A,int[] B){
    int tmp=0;
    while(i<A.length&&j<B.length&&A[i]==B[j]){
        tmp++;
        i++;
        j++;
    }
    return tmp;
}

动态规划

  • 递推公式:
if(A[i]==B[j]){
    dp[i][j]=dp[i-1][j-1]+1;
}else{
    dp[i][j]=0;
}
  • 可以先对第一行第一列的数据进行预处理,再进行匹配

代码

public int findLength(int[] A,int[] B){
    int max=0;
    int[][] dp=new int[A.length][B.length];
    //初始化dp[0][i]  第一行
    for(int i=0;i<B.length;i++){
        if(A[0]==B[i]){
            dp[0][i]=1;
        }
    }
    //初始化dp[i][0] 第一列
    for(int i=0;i<A.length;i++){
        if(A[i]==B[0]){
            dp[i][0]=1;
        }
    }
    for(int i=1;i<A.length;i++){
        for(int j=1;j<B.length;j++){
            if(A[i]==B[j]){
                dp[i][j]=dp[i-1][j-1]+1;
                max=Math.max(max,dp[i][j]);
            }
        }
    }
    return max;
}
  • 若不进行预处理,dp的长宽都加1,且dp的第一行第一列视为0(无数据对应)

代码如下:

public int findLength(int[] A,int[] B){
    int max=0;
    int[][] dp=new int[A.length+1][B.length+1];
    for(int i=1;i<=A.length;i++){
        for(int j=1;j<=B.length;j++){
            if(A[i-1]==B[j-1]){
                dp[i][j]=dp[i-1][j-1]+1;
            }else{
                dp[i][j]=0;
            }
            max=Math.max(max, dp[i][j]);
        }
    }
    return max;
}

滑动窗口

  • A固定,B移动;B固定,A移动

代码

//50ms
public class Solution4 {
    public int findLength(int[] A,int[] B){
        int n=A.length,m=B.length;
        int max=0;
        //固定B 移动A
        for(int i=0;i<n;i++){
            int len=Math.min(m, n-i);
            int maxLen=maxLength(A,B,i,0,len);
            max=Math.max(max, maxLen);
        }
		//固定A 移动B
        for(int i=0;i<m;i++){
            int len=Math.min(n,m-i);
            int maxLen=maxLength(A, B, 0, i, len);
            max=Math.max(max, maxLen);
        }
        return max;
    }

    //公共区域 最大匹配长度
    private int maxLength(int[] A, int[] B, int addA, int addB, int len) {
        int ans=0,k=0;
        for(int i=0;i<len;i++){
            if(A[addA+i]==B[addB+i]){
                k++;
            }else{
                k=0;
            }
            ans=Math.max(ans, k);
        }
        return ans;
    }
}

参考链接

官方题解

数据结构和算法:java动态规划和滑动窗口解决

@Alexand_ER:预处理dp的第一行第一列

原文地址:https://www.cnblogs.com/yh-simon/p/13222436.html