LintCode:最长上升子序列、最长公共子序列、最长公共子串

问题1:最长上升子序列

最长上升子序列的定义:

最长上升子序列问题是在一个无序的给定序列中找到一个尽可能长的由低到高排列的子序列,这种子序列不一定是连续的或者唯一的

分析:

动态规划,dp[i]表示到nums[i]为止的最长上升子序列长度。

dp[i]=max(dp[i],dp[j]+1),其中0<=j<i且nums[j]<nums[i]

其中,dp[i]初始都设为1,因为自身也是一个上升子序列。

public class Solution {
    /**
     * @param nums: An integer array
     * @return: The length of LIS (longest increasing subsequence)
     */
    public int longestIncreasingSubsequence(int[] nums) {
        // write your code here
        if(nums==null||nums.length==0)  return 0;
        int[] dp=new int[nums.length];
        int maxlength=0;
        for(int i=0;i<nums.length;i++){   //dp[i]表示到i数为止最长的上升子序列长度
            dp[i]=1;
            for(int j=0;j<i;j++) {
                if(nums[j]<nums[i]) {
                    dp[i] = Math.max(dp[i], dp[j]+1);
                }
            }
            maxlength=Math.max(dp[i],maxlength);
        }
        return maxlength;
    }
}

问题2:最长公共子序列

分析:最长公共子序列不一定连续。采用动态规划的方法,int[][] dp=new int[A.length()][B.length()];

dp[i][j]表示字符串A匹配到i,字符串B匹配到j时的最长公共子序列长度。

状态转移方程为:

        dp[i][j]=0  ,  i==0 || j==0

        dp[i][j]=dp[i-1][j-1]+1, A[i-1]==B[j-1]

        dp[i][j]=max(dp[i][j-1],dp[i-1][j]),  A[i-1]!=B[j-1]

变量maxlength保存最长长度,每得到一个dp中的值,就更新maxlength,最后返回即为最长长度。

public class Solution {
    /**
     * @param A: A string
     * @param B: A string
     * @return: The length of longest common subsequence of A and B
     */
    public int longestCommonSubsequence(String A, String B) {
        // write your code here
        if(A.length()==0 || B.length()==0) return 0;
        int[][] dp=new int[A.length()+1][B.length()+1];  //dp[i][j]表示字符串A匹配到i,字符串B匹配到j时的最大长度
        int maxLength=0;
        for(int i=1;i<=A.length();i++){
            for(int j=1;j<=B.length();j++){
                if(A.charAt(i-1)==B.charAt(j-1)){
                    dp[i][j]=dp[i-1][j-1]+1;
                }else{
                    dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
                }
                maxLength=Math.max(maxLength,dp[i][j]);
            }
        }
        return maxLength;
    }
}

问题3:最长公共子串

最长公共子串与最长公共子序列的唯一区别就是最长公共子串要求是连续的,而子序列可以不连续。

只修改状态转移方程那部分:

        dp[i][j]=0  ,  i==0 || j==0  或 A[i-1]!=B[j-1]

        dp[i][j]=dp[i-1][j-1]+1, A[i-1]==B[j-1]

public class Solution {
    /**
     * @param A: A string
     * @param B: A string
     * @return: the length of the longest common substring.
     */
    public int longestCommonSubstring(String A, String B) {
        // write your code here
        if(A.length()==0 || B.length()==0) return 0;
        int[][] dp=new int[A.length()+1][B.length()+1];  //dp[i][j]表示字符串A匹配到i,字符串B匹配到j时的最大长度
        int maxLength=0;
        for(int i=1;i<=A.length();i++){
            for(int j=1;j<=B.length();j++){
                if(A.charAt(i-1)==B.charAt(j-1)){
                    dp[i][j]=dp[i-1][j-1]+1;
                }else{
                    dp[i][j]=0;
                }
                maxLength=Math.max(maxLength,dp[i][j]);
            }
        }
        return maxLength;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_27139155/article/details/80689825