[英]Longest palindromic substring top down recursive approach
我正在嘗試解決 Leetcode 上最長的回文substring。 我知道這個問題的解決方案,比如圍繞中心展開或動態編程自下而上的方法。 出於純粹的教育目的,我想以自上而下的遞歸方式解決這個問題。 我正在嘗試找到類似於此處或此處描述的解決方案。 (問題略有不同)。 我有這個 function:
private (int Start, int End) Longest(string s, int i, int j)
這需要字符串 + 開始和結束 position 搜索。 返回的元組是最長回文的開始和結束。 我試圖分成這些情況:
當然,我使用以元組 (int, int) 作為鍵(i 和 j 的值)的字典來記住所有計算結果,以便不再計算它們。
完整的代碼如下,但是當我嘗試修復算法時,經過幾次迭代后它非常混亂。 我相信創建代碼不是很重要。
代碼似乎返回了正確的結果,但在 Leetcode 上的 Time Limit Exceeded 上失敗了。 是否有正確的快速遞歸解決方案? 我相信應該存在 DP 自下而上的解決方案。
代碼:
private readonly IDictionary<(int, int), (int, int)> _mem = new Dictionary<(int, int), (int, int)>();
private (int Start, int End) Longest(string s, int i, int j) {
if (i >= j) {
return (i, j);
}
if (_mem.TryGetValue((i, j), out var ret)) {
return ret;
}
var newI = i + 1;
var newJ = j - 1;
ValueTuple<int, int> removingTwo;
if (s[i] == s[j])
{
removingTwo = Longest(s, newI, newJ);
if (removingTwo.Item1 == newI && removingTwo.Item2 == newJ) {
removingTwo.Item1--;
removingTwo.Item2++;
}
}
else {
removingTwo = (1, 0);
}
var removingFirst = Longest(s, newI, j);
var removingLast = Longest(s, i, newJ);
var mT = removingTwo.Item2 - removingTwo.Item1;
var mF = removingFirst.End - removingFirst.Start;
var mL = removingLast.End - removingLast.Start;
var max = Math.Max(mT, mF);
max = Math.Max(max, mL);
ValueTuple<int, int> retVal;
if (max == mT) retVal = removingTwo;
else if (max == mF) retVal = removingFirst;
else retVal = removingLast;
_mem.Add((i, j), retVal);
return retVal;
}
編輯:工作自下而上的解決方案(從geegsforgeegs復制):
public string LongestPalindrome(string s) {
if (s.Length == 0) return "";
var table = new bool[s.Length, s.Length];
var len = s.Length;
for (int i = 0; i < len; i++) {
table[i,i] = true;
}
var start = 0;
var max = 1;
for (int i = 0; i < len - 1; i++) {
if (s[i] == s[i + 1]) {
start = i;
max = 2;
table[i, i+1] = true;
}
}
for (int k = 3; k <= len; ++k) {
// Fix the starting index
for (int i = 0; i < len - k + 1; ++i)
{
// Get the ending index of substring from
// starting index i and length k
int j = i + k - 1;
// checking for sub-string from ith index to
// jth index iff str.charAt(i+1) to
// str.charAt(j-1) is a palindrome
if (table[i + 1, j - 1] && s[i] == s[j]) {
table[i,j] = true;
if (k > max) {
start = i;
max = k;
}
}
}
}
return s.Substring(start, max);
}
這是 Python 中通過 LeetCode 測試的遞歸方法。 可能他們正在尋找一個恆定的空間解決方案。
f(i, k)
返回(l, j)
,長度為l
的最大元組及其起始索引j
。 在這種情況下, max
正在查看返回元組的第一個元素,即l
,即回文的長度。
def longestPalindrome(self, s):
def f(i, k):
return max(
# next iteration
f(i - 1, 1) if k < 2 and i > 0 else (-1,-1),
f(i - 1, 2) if k < 2 and i > 0 and s[i-1] == s[i] else (-1, -1),
# a larger palindrome than this one
f(i - 1, k + 2) if i > 0 and i + k < len(s) and s[i-1] == s[i + k] else (-1, -1),
# this one
(k, i)
)
(l, j) = f(len(s) - 1, 1)
return s[j:j+l]
簡單的遞歸解決方案,不是記憶
def palandrom(A,i,j):
if i > j:
return ''
elif i == j:
return A[i]
elif A[i] == A[j]:
save = A[i+1 : j]
if save == save[::-1]:
i = len(A) #As we know rest of string are palandrome we want to make i>j condition true
return (A[i] + save + A[j])
left = palandrom(text,i+1,j)
right = palandrom(text,j,j+1)
return left if len(left) > len(right) else right
print(palandrom(loiol,0,4))
使用 Python 在字符串中找到最長可能回文的最佳解決方案
inp=input("Enter a string:\n")
tmp=''
pal=[]
for i in inp:
tmp+=i
if tmp==tmp[::-1] and len(tmp)>1:
pal.append(tmp)
tmp=''
print(pal)
if len(pal)>0:
tmp=sorted(pal,key=len)
print(f'Longest palindrome : {tmp[-1]}')
else:
print("No pattern found except individual letters!")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.