【问题标题】:Longest Common Subsequence memoization method gives Time Limit Error on LeetCodeLongest Common Subsequence memoization 方法在 LeetCode 上给出 Time Limit Error
【发布时间】:2020-12-28 14:23:36
【问题描述】:

为什么我的用于查找Longest Common Subsequence 的 c++ 实现在 LeetCode 上给出了time limit error。如何提高该算法的时间复杂度?

    int longestCommonSubsequence(string text1, string text2) {
        int n1 = text1.length(), n2 = text2.length();
        vector<vector<int>> dp(n1+1, vector<int>(n2+1, -1));
        longestCommonSubsequence(text1, text2, n1, n2, dp);
        return dp[n1][n2];
    }
    int longestCommonSubsequence(string text1, string text2, int n1, int n2, 
                                  vector<vector<int>> &dp) {
        if(n1==0 || n2==0) {
            return 0;
        }
        
        if(dp[n1][n2] != -1) {
            return dp[n1][n2];
        }
        
        if(text1[n1-1]==text2[n2-1]) {
            dp[n1][n2] = 1 + longestCommonSubsequence(text1, text2, n1-1, n2-1, dp);
            return dp[n1][n2];
        }
        else {
            dp[n1][n2] = max(longestCommonSubsequence(text1, text2, n1-1, n2, dp), 
                       longestCommonSubsequence(text1, text2, n1, n2-1, dp));
            return dp[n1][n2];
        }
    }

【问题讨论】:

  • 不知道是否重要,但您可以通过 const 引用而不是值传递 text1text2
  • 真的需要分配(n1+1)x(n2+1)的矩阵吗? n1xn2 不够吗?另外,我想知道它是否有助于从 n1/2 开始,寻找对数复杂度而不是线性。如果这与记忆化相得益彰,可能值得考虑。

标签: c++ algorithm memoization


【解决方案1】:

我们可以不用递归来解决这个问题,类似地使用动态规划。如果没有 TLE,这将通过:

// The following block might slightly improve the execution time;
// Can be removed;
static const auto __optimize__ = []() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    return 0;
}();

// Most of headers are already included;
// Can be removed;
#include <cstdint>
#include <string>
#include <vector>
#include <algorithm>

using ValueType = std::uint_fast16_t;

static const struct Solution {
    static const int longestCommonSubsequence(
        const std::string& text_a,
        const std::string& text_b
    ) {
        const ValueType a_len = std::size(text_a);
        const ValueType b_len = std::size(text_b);
        std::vector<std::vector<ValueType>> dp(a_len + 1, std::vector<ValueType>(b_len + 1));

        for (ValueType a = 1; a <= a_len; ++a) {
            for (ValueType b = 1; b <= b_len; ++b) {
                if (text_a[a - 1] == text_b[b - 1]) {
                    dp[a][b] = 1 + dp[a - 1][b - 1];

                } else {
                    dp[a][b] = std::max(dp[a - 1][b], dp[a][b - 1]);
                }
            }
        }

        return dp[a_len][b_len];
    }
};

【讨论】:

    【解决方案2】:

    将 text1 和 text2 作为引用发送,因为如果我们通过值传递它,则每次递归调用都会创建一个字符串的副本,这对于每个递归调用来说都是额外的 O(string_length) 开销。

    【讨论】:

      猜你喜欢
      • 2018-12-09
      • 1970-01-01
      • 1970-01-01
      • 2020-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-24
      • 1970-01-01
      相关资源
      最近更新 更多