题解 | #最长公共子数组#

最长公共子数组

http://www.nowcoder.com/practice/6032826d387c4a10ad3690cce5fdb015

题意理解

求两个数组最长的公共连续子数组的长度。

方法一

动态规划
使用一个二维数组dp,其中dp[i][j]表示A中子串以A[i]结尾且B中子串以B[j]结尾时,它们满足是公共子串的长度。显然,当两者不等时,以它们结尾的子串不可能是公共子串;当两者相等时,可以使前面的公共子串的长度加1。状态转移方程如下:
dp[i][j]=dp[i1][j1]+1(A[i]==B[j])dp[i][j] = dp[i-1][j-1]+1 (A[i]==B[j])
dp[i][j]=0(A[i]!=B[j])dp[i][j] = 0 (A[i]!=B[j])

注意要设置dp的边界,数组元素相等时为1,不等时为0。我们在计算dp[i][j]的时候同时更新最后的最长长度ans。

以[22561,2256]为例,dp数组的值如下图所示: alt

具体代码如下:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param A int整型vector 
     * @param B int整型vector 
     * @return int整型
     */
    int longestCommonSubarry(vector<int>& A, vector<int>& B) {
        // write code here
        vector<vector<int>> dp(A.size(),vector<int> (B.size(),0));
        int ans = 0;
        //初始化
        for (int i=0;i<A.size();i++)
            if (A[i]==B[0]) dp[i][0] = 1;
        for (int i=0;i<B.size();i++)
            if (A[0]==B[i]) dp[0][i] = 1;
        for (int i=1;i<A.size();i++)
        {
            for (int j=1;j<B.size();j++)
            {
                if (A[i]==B[j])
                {
                    dp[i][j] = dp[i-1][j-1] + 1;
                    ans = max(ans, dp[i][j]);
                }
                //如果不等,dp为0
                else dp[i][j] = 0;
            }
        }
        return ans;
    }
};

时间复杂度: O(N^2)。双重循环,外侧循环遍历这个A,内侧循环遍历整个B,长度均为N。
空间复杂度: O(N^2)。使用了二维数组dp,其长宽分别为A、B的长度。

方法二

枚举
我们枚举所有子数组的开头和子数组的长度。前面两重循环分别枚举A中子数组的起始位置i和B的子数组的起始位置j,第三重循环枚举连续公共子数组的长度,如果出现某两个元素不相等了就停止,说明此时已经得到以A[i]、B[j]开头的连续子数组的最大长度。如果相等,那么枚举的长度继续递增,同时更新ans。

具体代码如下:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param A int整型vector 
     * @param B int整型vector 
     * @return int整型
     */
    int longestCommonSubarry(vector<int>& A, vector<int>& B) {
        // write code here
        int ans = 0;
        //枚举所有可能的子数组的情况
        for (int i=0;i<A.size();i++)
            for (int j=0;j<B.size();j++)
            {
                for (int k=0;k<A.size()-i&&k<B.size()-j;k++)
                    if (A[i+k]!=B[j+k])
                    {
                        //及时跳出循环
                        break;
                    }
                    else ans = max(ans, k+1);
            }
        return ans;
    }
};

时间复杂度: O(N^3)。三重循环,每重循环的最坏情况对应的次数均为N。
空间复杂度: O(1)。没有开辟新空间。

全部评论

相关推荐

11-04 14:10
东南大学 Java
_可乐多加冰_:去市公司包卖卡的
点赞 评论 收藏
分享
牛客717484937号:双飞硕没实习挺要命的
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务