是不是每一个自下而上的DP都有对应的自上而下的实现?
Is it true that every bottom-up DP has a corresponding top-down realization?
我正在尝试解决这个 Longest Palindromic Substring 问题,其中 returns 是给定字符串 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;
}
如何修改我的自上而下算法以与上述自下而上算法竞争?是不是每个bottom-up DP都有对应的时间复杂度相同的top-down方法?
这种方法是自上而下的 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
我正在尝试解决这个 Longest Palindromic Substring 问题,其中 returns 是给定字符串 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;
}
如何修改我的自上而下算法以与上述自下而上算法竞争?是不是每个bottom-up DP都有对应的时间复杂度相同的top-down方法?
这种方法是自上而下的 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