【问题标题】:Is it true that every bottom-up DP has a corresponding top-down realization?是不是每一个自下而上的DP都有对应的自上而下的实现?
【发布时间】:2021-09-11 00:08:58
【问题描述】:

我正在尝试解决这个Longest Palindromic Substring 问题,它返回给定字符串s 中最长的回文子字符串。我应该在O(n^2) 时间用 DP 解决这个问题。这是我的代码:

class Solution:
    def longestPalindrome(self, s: str) -> str:
        # DP
        h = {} #memoization
        
        def dp(i, j): # DP algorithm to compute if the substring s[i:j+1] is palindrome
            nonlocal s, h
            if (i,j) in h: return h[(i, j)]
            else:
                if j - i <= 1:
                    f = s[i] == s[j]
                else:
                    f = dp(i+1, j-1) and s[i] == s[j]
                h[(i, j)] = f
                return f

        res,start, end = 0, 0, 0
        
        for i in range(len(s)):
            for j in range(i,len(s)): # All possible substring
                if (i,j) in h: temp = h[(i,j)]
                else: temp = dp(i, j)
                if temp == True and j - i + 1 > res:
                    res = j-i+1
                    start = i
                    end = j
        return s[start:end+1]

这个解决方案超出了时间限制,我不确定我的算法在哪里可以优化。然后我检查了解决方案,发现了一种自下而上的DP算法:

public String longestPalindrome(String s) {
  int n = s.length();
  String res = null;
    
  boolean[][] dp = new boolean[n][n];
    
  for (int i = n - 1; i >= 0; i--) {
    for (int j = i; j < n; j++) {
      dp[i][j] = s.charAt(i) == s.charAt(j) && (j - i < 3 || dp[i + 1][j - 1]);
            
      if (dp[i][j] && (res == null || j - i + 1 > res.length())) {
        res = s.substring(i, j + 1);
      }
    }
  }
    
  return res;
}

如何修改自上而下的算法以与上述自下而上的算法竞争?是不是每个自底向上的DP都有对应的自顶向下方法,时间复杂度相同?

【问题讨论】:

  • 很可能是这样。但是对于这种情况,你可以在没有 DP 的情况下做得很好。
  • 感谢您的评论。我知道这个问题不用DP就可以解决,但是我正在学习DP。具体来说,我想要一个自上而下的 DP 解决方案。
  • 发布另一个 DP 版本。它有效,但效率不高。

标签: recursion iteration dynamic-programming


【解决方案1】:

这种方法是自上而下的 DP 方法,但它效率不高。与我之前发布的自下而上或直接的方法相比。

 def longestPalindrome(self, s: str) -> str:
     if not s: return s
     res = ''
     n = len(s)
     dp = [[False for _ in range(n)] for _ in range(n)]
     mx  = 0
     for j in range(n):
         for i in range(0, j+1):
             dp[i][j] = ((s[i] == s[j]) and ((j - i <= 2) or dp[i+1][j-1]))
             if dp[i][j]:
                if (j-i+1) > mx:
                    mx  = j-i+1
                    res = s[i:j+1]
     return res

【讨论】:

  • 谢谢,请问为什么这种自顶向下的实现比自底向上的实现差?我认为它们应该是一样的?
  • 这背后有很好的理论。但我建议您为此发布另一个问题。 “一个问题一个帖子。”
猜你喜欢
  • 1970-01-01
  • 2016-04-26
  • 2015-02-20
  • 2020-10-19
  • 2021-10-30
  • 1970-01-01
  • 2021-10-16
  • 2010-10-14
  • 1970-01-01
相关资源
最近更新 更多