在Python中查找字符串中最长的回文
我正在努力解决LeetCode上的问题。问题陈述是: 给定一个字符串s,查找s中最长的回文子字符串。您可以假定s的最大长度为1000 例如: 注:“aba”也是一个有效答案。 例如: 我提出了以下解决方案(包括一些测试用例):在Python中查找字符串中最长的回文,python,algorithm,Python,Algorithm,我正在努力解决LeetCode上的问题。问题陈述是: 给定一个字符串s,查找s中最长的回文子字符串。您可以假定s的最大长度为1000 例如: 注:“aba”也是一个有效答案。 例如: 我提出了以下解决方案(包括一些测试用例): 导入pytest 类解决方案: def最长回文(self,s): 候选者=“” 最长=“” 包含回文=False 对于i,枚举中的字符: 如果i==0: 候选字符 elif i==1: 如果s[1]==s[0]: 候选者=self.get_回文(s,开始=0,结束=1)
导入pytest
类解决方案:
def最长回文(self,s):
候选者=“”
最长=“”
包含回文=False
对于i,枚举中的字符:
如果i==0:
候选字符
elif i==1:
如果s[1]==s[0]:
候选者=self.get_回文(s,开始=0,结束=1)
如果i>=2:
如果char==s[i-1]:
候选者=self.get_回文(s,start=i-1,end=i)
elif char==s[i-2]:
候选者=self.get_回文(s,start=i-2,end=i)
如果len(候选)>len(最长):
最长=候选人
回程最长
@静力学方法
def get_回文(s,开始,结束):
回文=s[开始:结束+1]
当末端0)和(结束<长度-1):
开始-=1
结束+=1
如果s[start]==s[end]:
回文组=s[start]+回文组+s[end]
其他:
打破
返回回文
@静力学方法
定义所有相同(项目):
返回全部(项中的项的项==项[0]
def测试_1():
assert Solution().longestPalindrome(“babad”)=“bab”
def测试_2():
断言解决方案().longestPalindrome(“cbbd”)=“bb”
def测试_3():
assert Solution().longestPalindrome(“abba”)=“abba”
def测试_4():
assert Solution().longestPalindrome(“a”)=“a”
def测试_5():
断言解决方案().longestPalindrome(“ccc”)=“ccc”
def测试_6():
assert Solution().longestPalindrome(“aaaa”)=“aaaa”
def测试_7():
assert Solution().longestPalindrome(“aaabaaa”)=“aaabaaa”
如果名称=“\uuuuu main\uuuuuuuu”:
pytest.main([[uuuuu文件])
问题是我得到了一个“超过时间限制”错误:
我的理解是,该算法的时间复杂度为O(n^2),因为它会检查每个字符的回文长度,可能多达n个字符。LeetCode的解决方案中还有O(n^2)算法(Java)
我猜Python的时间限制有点太严格了,它比Java慢。或者我遗漏了什么,并且我的解决方案的时间复杂度实际上大于O(n^2)?您失败的测试字符串似乎只由a组成。这是最坏的情况,它实际上是O(n³)而不是O(n²),因为在
中有另一个隐藏循环。(起初,我还认为字符串上的slice操作符[:]
会进行复制,但事实并非如此。)
您需要调用所有相同的
,因为您在主函数中区分了“aa”和“aba”两种情况。但是您不需要在循环中这样做,因为您将只在第一个中添加相同的字母,而在获取回文中循环。因此,一个快速解决方案是只测试一次所有字符是否相同:
if Solution.all_same(palindrome):
while end < len(s) - 1:
if s[end+1] == s[start]:
end += 1
palindrome += s[end]
else:
break
总的来说,代码看起来相当不整洁,带有所有的中断和不必要的大小写区分。为什么要将索引和回文
作为单独的实体保存在获取回文
中,而您必须保持同步
在我看来,这是一个更整洁的版本:
class Solution:
def longestPalindrome(self, s):
longest = ""
for i, _ in enumerate(s):
candidate = self.get_palindrome(s, start = i, end = i)
if len(candidate) > len(longest):
longest = candidate
return longest
@staticmethod
def get_palindrome(s, start, end):
while end + 1 < len(s) and s[end+1] == s[start]:
end += 1
while start > 0 and end + 1 < len(s) and s[start - 1] == s[end + 1]:
start -= 1
end += 1
return s[start:end + 1]
这在“abababab”这样的字符串上仍然不理想,但在您的情况下应该足够快。我尝试了“动态规划”的思想,即找到“0阶”回文的中心,然后随着深度的增加和不匹配的发生而修剪
修剪是在列表comps中完成的,应该相对较快,但仍然是O(n^2)
这是我发现的获取最长回文及其长度的方法。我认为这很容易理解
首先,我将这个单词添加到一个字符数组中,然后我将第一个字母与所有其他字母向后检查。然后继续下一个字符。使用if-else和for循环得到答案,最后使用hashset得到最长的回文
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println(longestPalSubstr(in.nextLine().toLowerCase()));
}
static String longestPalSubstr(String str) {
char [] input = str.toCharArray();
Set<CharSequence> out = new HashSet<CharSequence>();
int n1 = str.length()-1;
for(int a=0;a<=n1;a++)
{
for(int m=n1;m>a;m--)
{
if(input[a]==input[m])
{
String nw = "",nw2="";
for (int y=a;y<=m;y++)
{
nw=nw+input[y];
}
for (int t=m;t>=a;t--)
{
nw2=nw2+input[t];
}
if(nw2.equals(nw))
{
out.add(nw);
break;
}
}
}
}
int a = out.size();
int maxpos=0;
int max=0;
Object [] s = out.toArray();
for(int q=0;q<a;q++)
{
if(max<s[q].toString().length())
{
max=s[q].toString().length();
maxpos=q;
}
}
String output = "longest palindrome is : "+s[maxpos].toString()+" and the lengths is : "+ max;
return output;
}
publicstaticvoidmain(字符串[]args){
扫描仪输入=新扫描仪(系统输入);
System.out.println(longestPalSubstr(in.nextLine().toLowerCase());
}
静态字符串longestplasubstr(字符串str){
char[]input=str.toCharArray();
Set out=新的HashSet();
int n1=str.length()-1;
对于(int a=0;aa;m--)
{
如果(输入[a]==输入[m])
{
字符串nw=“”,nw2=“”;
对于(int y=a;y=a;t--)
{
nw2=nw2+输入[t];
}
如果(nw2.等于(nw))
{
加上(西北);
打破
}
}
}
}
int a=out.size();
int-maxpos=0;
int max=0;
对象[]s=out.toArray();
对于(intq=0;qI)来说,没有深入研究您的代码,但实际上标准的方法是使用动态编程。我猜时间限制“知道”big-O的工作原理是什么,也就是说,它是一个渐进的东西。所以它会以某种方式得到一个估计,你的解决方案需要n的时间,然后看看你在100n或类似的情况下做什么。然后使用一个足够大的n,这样设置成本就无关紧要了。我提交了第一个解决方案,它被接受了。事实上,我错过了所有相同的方法d也是O(n),所以我运行的是O(n^3)方法,而不是O(n^2)方法。(您的解决方案也确实更整洁;开始扩展是有意义的。)
if Solution.all_same(palindrome):
while end < len(s) - 1:
if s[end+1] == s[start]:
end += 1
palindrome += s[end]
else:
break
elif i >= 2:
if char == s[i-1]:
candidate = self.get_palindrome(s, start=i-1, end=i)
else:
candidate = self.get_palindrome(s, start=i, end=i)
class Solution:
def longestPalindrome(self, s):
longest = ""
for i, _ in enumerate(s):
candidate = self.get_palindrome(s, start = i, end = i)
if len(candidate) > len(longest):
longest = candidate
return longest
@staticmethod
def get_palindrome(s, start, end):
while end + 1 < len(s) and s[end+1] == s[start]:
end += 1
while start > 0 and end + 1 < len(s) and s[start - 1] == s[end + 1]:
start -= 1
end += 1
return s[start:end + 1]
class Solution:
def longestPalindrome(self, s):
longest = ""
i = 0
l = len(s)
while i < l:
end = i
while end + 1 < l and s[end + 1] == s[i]:
end += 1
candidate = self.get_palindrome(s, i, end)
if len(candidate) > len(longest):
longest = candidate
i = end + 1
return longest
@staticmethod
def get_palindrome(s, start, end):
while start > 0 and end + 1 < len(s) and s[start - 1] == s[end + 1]:
start -= 1
end += 1
return s[start:end + 1]
class Solution:
def longestPalindrome(self, s):
s = '>' + s + '<' # add guard values
# make lists of '0_th order' palindrome 'centers', even and odd
evn = [i for i, a in enumerate(zip(s, s[1:])) if a[0] == a[1]]
odd = [i + 1 for i, a in enumerate(zip(s, s[2:])) if a[0] == a[1]]
# prune lists of centers when elements +/- j from centers don't match
evn_last, odd_last = [[1], 0], [[1], 1]
j = 1
while evn:
evn_last = (evn, j)
evn = [e for e in evn if s[e - j] == s[e + j + 1]]
j += 1
j = 1
while odd:
odd_last = (odd, j)
odd = [e for e in odd if s[e - j] == s[e + j]]
j += 1
# determine longest, construct palindrome
if 2 * evn_last[1] > 2 * odd_last[1] - 1:
cntr = evn_last[0][0]
pal = s[cntr] + s[cntr + 1]
for i in range(1, evn_last[1]):
pal = s[cntr - i] + pal + s[cntr + i + 1]
else:
cntr = odd_last[0][0]
pal = s[cntr]
for i in range(1, odd_last[1]):
pal = s[cntr - i] + pal + s[cntr + i]
return pal
S = Solution()
%timeit S.fred_longestPalindrome("aba"*300)
17.8 ms ± 230 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit S.Kurt_longestPalindrome("aba"*300)
52.8 ms ± 108 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println(longestPalSubstr(in.nextLine().toLowerCase()));
}
static String longestPalSubstr(String str) {
char [] input = str.toCharArray();
Set<CharSequence> out = new HashSet<CharSequence>();
int n1 = str.length()-1;
for(int a=0;a<=n1;a++)
{
for(int m=n1;m>a;m--)
{
if(input[a]==input[m])
{
String nw = "",nw2="";
for (int y=a;y<=m;y++)
{
nw=nw+input[y];
}
for (int t=m;t>=a;t--)
{
nw2=nw2+input[t];
}
if(nw2.equals(nw))
{
out.add(nw);
break;
}
}
}
}
int a = out.size();
int maxpos=0;
int max=0;
Object [] s = out.toArray();
for(int q=0;q<a;q++)
{
if(max<s[q].toString().length())
{
max=s[q].toString().length();
maxpos=q;
}
}
String output = "longest palindrome is : "+s[maxpos].toString()+" and the lengths is : "+ max;
return output;
}
class Solution:
def longestPalindrome(self, s):
paliandr = ''
len_s = len(s)
def if_pal_singl(s,i,dabl):
pal = s[i-dabl:i+1]
indx_left = i-dabl
indx_right = i
while (indx_left-1 in range(len_s) and indx_right+1 in range(len_s)):
indx_left -=1
indx_right +=1
if s[indx_left] == s[indx_right]:
pal = s[indx_left]+pal+s[indx_right]
else:
break
return pal
dabl = 0
for i in range(1,len_s-1):
if s[i] == s[i+1]:
dabl+=1
continue
pal = if_pal_singl(s,i,dabl)
dabl = 0
if len(pal) > len(paliandr):
paliandr = pal
print (paliandr)
if __name__ == "__main__":
Solution().longestPalindrome('abababab')