我想在Leetcode上解决Longest palindromic substring . 我知道这个问题的解决方案,如围绕中心扩展或dynamic programming bottom up approach . 出于纯粹的教育目的,我想以自上而下的递归方式解决这个问题 . 我试图找到类似于描述here或here的解决方案 . (问题略有不同) . 我有这个功能:
private (int Start, int End) Longest(string s, int i, int j)
它采用搜索的字符串开始和结束位置 . 返回的元组是最长的回文的开始和结束 . 我试图分裂成这些情况:
如果s [i] == s [j]调查最长(s,i 1,j-1)
调查最长(s,i 1,j)
调查时间最长(s,i,j - 1)
从这三个中返回最长(返回的开始和结束之间的最大差异)
当然我使用带有tuple(int,int)的Dictionary作为键(i和j的值)来记住所有计算结果,以便不再计算它们 .
完整代码如下,但在我尝试修复算法后几次迭代后它非常混乱 . 我相信concreate代码不是很重要 .
代码似乎返回正确的结果但在Leetcode上超过时间限制时失败 . 有正确的快速递归解决方案吗?我相信应该存在DP自下而上的解决方案 .
码:
private readonly IDictionary _mem = new Dictionary();
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 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 retVal;
if (max == mT) retVal = removingTwo;
else if (max == mF) retVal = removingFirst;
else retVal = removingLast;
_mem.Add((i, j), retVal);
return retVal;
}