LeetCode1143、最長共通部分列

タイトル説明

https://leetcode-cn.com/problems/longest-common-subsequence/
ここに画像の説明を挿入

解決

(1)トップダウン再帰(動的計画法)

class Solution {
    
    
 // 备忘录,消除重叠子问题
int[][] memo;

/* 主函数 */
int longestCommonSubsequence(String s1, String s2) {
    
    
    int m = s1.length(), n = s2.length();
    // 备忘录值为 -1 代表未曾计算
    memo = new int[m][n];
    for (int[] row : memo) 
        Arrays.fill(row, -1);
    // 计算 s1[0..] 和 s2[0..] 的 lcs 长度
    return dp(s1, 0, s2, 0);
}

// 递归函数,自顶向下的递推,其问题的定义:计算 s1[i..] 和 s2[j..] 的最长公共子序列长度
int dp(String s1, int i, String s2, int j) {
    
    
    if (i == s1.length() || j == s2.length()) {
    
    
        return 0;
    }
    // 如果之前计算过,则直接返回备忘录中的答案
    if (memo[i][j] != -1) {
    
    
        return memo[i][j];
    }
    // 根据 s1[i] 和 s2[j] 的情况做选择
    if (s1.charAt(i) == s2.charAt(j)) {
    
    
        // s1[i] 和 s2[j] 必然在 lcs 中
        memo[i][j] = 1 + dp(s1, i + 1, s2, j + 1);
    } else {
    
    
        // s1[i] 和 s2[j] 至少有一个不在 lcs 中
        memo[i][j] = Math.max(
            dp(s1, i + 1, s2, j),
            dp(s1, i, s2, j + 1)
        );
    }
    return memo[i][j];
}
}

ここに画像の説明を挿入

(2)ボトムアップ動的計画法

class Solution {
    
    
    public int longestCommonSubsequence(String text1, String text2) {
    
    
       if(text1==null || text2==null) return 0;
       int  m = text1.length(),n=text2.length();

       int [][]dp = new int[m+1][n+1];
       //边界
       //dp[0][..]表示s1[-1]和s2[...]的最长公共子序
       //dp[..][0]表示s2[-1]和s1[...]的最长公共子序
       //均为0

       //状态递推--严格遵循定义的dp数组 dp[i][j]表示是s1[0,i-1]和s1[0,j-1]的最长公共子序
       for(int i=1;i<=m;i++){
    
    
           for(int j=1;j<=n;j++){
    
    
               if(text1.charAt(i-1)==text2.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]);
               }
           }
       }
       return dp[m][n];


    }
}

ここに画像の説明を挿入

経験:

  • 自分で定義したdp配列の意味に厳密に従って、再帰方程式を導き出します。
  • 状態方程式を再帰させるための短い実用的な例を見てください
  • トップダウンとボトムアップの動的計画法のdp配列には、反対の意味があります。
  • 文字列dp問題は通常、ダブルポインターを使用し、i、jで終わるサブ問題の解決策またはi、jで始まるサブ問題の解決策のいずれかを使用します。

おすすめ

転載: blog.csdn.net/qq_44861675/article/details/114478184