文章目录
- 最长回文子串(python)多种解法
- 反转列表的三种方法
- 二维数组赋值问题
最长回文子串(python)多种解法
题目:给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
解法一:
暴力解法,列出所有子字符串,判断其是否为回文子串,并保留最长回文子串。
(时间超出leetcode的时间限制ahhhhh)
array1=list(i for i in input().split())
#array2=list(i for i in input().split())
def isPalindromic(s):
if len(s)==1:
return True
else:
for i in range(len(s)//2):
if s[i]!=s[len(s)-1-i]:
return False
return True
max_len=0
max_Palindrome_str=""
max_Palindrome=[]
for i in range(len(s)):
for j in range(i,len(s)):
if isPalindromic(s[i:j+1])==True:
if len(s[i:j+1])>max_len:
max_len=len(s[i:j+1])
max_Palindrome=s[i:j+1]
#print(max_Palindrome)
for i in range(len(max_Palindrome)):
max_Palindrome_str=max_Palindrome_str+max_Palindrome[i]
return max_Palindrome_str
print(longestPalindrome(array1))
时间复杂度:两层 for 循环 O(n²),for 循环里边判断是否为回文 O(n),所以时间复杂度为 O(n³)。
空间复杂度:O(1),常数个变量。
解法二:
最长公共子串法(1),找出该字符串和反转的字符串公共部分,并且看对应下标是否一致。
array1=list(i for i in input().split())
def longestPalindrome(s):
if s==None:
return ""
s_reverse=list(reversed(s))
length=len(s)
max_len=0
max_end=0
a = [[0] * length for x in range(length)] #len长len列
for i in range(length):
for j in range(length):
if s[i]==s_reverse[j]:
if i==0 or j==0:
a[i][j]=1
else:
a[i][j]=a[i-1][j-1]+1
if a[i][j]>max_len and length-1-j+a[i][j]-1==i:#j对应翻转前的位置再加上最大回文子串长度是否等于i
max_len=a[i][j]
max_end=i
return s[max_end-max_len+1:max_end+1]
print(longestPalindrome(array1))
时间复杂度 O(n²)。
空间复杂度降为 O(n²)。
执行用时5696 ms
内存消耗38.9 MB
解法三 :
最长公共子串法优化(2)
array1=list(i for i in input().split())
def longestPalindrome(s):
if s==None:
return ""
s_reverse=list(reversed(s))
length=len(s)
max_len=0
max_end=0
a = [0] * length
for i in range(length):
for j in range(length-1,-1,-1):#注意:要倒过来,因为正过来时,需要的上一轮的数据被这一轮数据更新了
if s[i]==s_reverse[j]:
if i==0 or j==0:
a[j]=1
else:
a[j]=a[j-1]+1
else:
a[j]=0
if a[j]>max_len and length-1-j+a[j]-1==i:#j对应翻转前的位置再加上最大回文子串长度是否等于i
max_len=a[j]
max_end=i
return s[max_end-max_len+1:max_end+1]
print(longestPalindrome(array1))
时间复杂度 O(n²)。
空间复杂度降为 O(n)。
执行用时 5068 ms
内存消耗 13.7 MB
解法四:暴力破解优化(1)
array1=list(i for i in input().split())
def longestPalindrome(s):
length=len(s)
max_len=0
max_Palindrome=[]
max_Palindrome_str=""
p=[[0]*length for x in range(length)]
if length==0:
return ""
for lenh in range(1,length+1):
for start in range(length):
end=start+lenh-1
if end>=length:
break
p[start][end] = (lenh == 1 or lenh == 2 or p[start + 1][end - 1]) and s[start] == s[end]
if p[start][end] and lenh > max_len:
max_len = lenh
max_Palindrome = s[start:end + 1]
for i in range(len(max_Palindrome)):
max_Palindrome_str = max_Palindrome_str + max_Palindrome[i]
return max_Palindrome_str
"""
if lenh == 1:
p[start][end] = True
elif lenh == 2:
if s[start] == s[end]:
p[start][end] = True
else:
if s[start] == s[end] and p[start + 1][end - 1]==True:
p[start][end] = True
"""
print(longestPalindrome(array1))
时间复杂度:两层循环 O(n²)。
空间复杂度:用二维数组 P 保存每个子串的情况 O(n²)。
执行用时 4716ms
内存消耗 21.4 MB
解法五:暴力破解优化(2)
array1=list(i for i in input().split())
def longestPalindrome(s):
length=len(s)
max_len=0
res=[]
res_str=""
a=[[0]*length for _ in range(length)]
for i in range(length-1,-1,-1):#注:倒序,因为不像上一种方法,已有初始值。
for j in range(i,length):
a[i][j]=(j-i<2 or a[i+1][j-1]) and s[i]==s[j]#j-i为两者间距离
if a[i][j] and j-i+1>max_len:
max_len=j-i+1
res=s[i:j+1]
for i in range(len(res)):
res_str=res_str+res[i]
return res_str
print(longestPalindrome(array1))
时间复杂度:两层循环 O(n²)。
空间复杂度:用二维数组 a 保存每个子串的情况 O(n²)。
执行用时 4364 ms
内存消耗 21.5 MB
解法五:暴力破解优化之优化(2)
array1=list(i for i in input().split())
def longestPalindrome(s):
length=len(s)
max_len=0
res=[]
res_str=""
a=[[0]*length for _ in range(length)]
for i in range(length-1,-1,-1):#注:倒序,因为不像上一种方法,已有初始值。
for j in range(length-1,i-1,-1):
a[j]=(j-i<2 or a[j-1]) and s[i]==s[j]#j-i为两者间距离
if a[j] and j-i+1>max_len:
max_len=j-i+1
res=s[i:j+1]
for i in range(len(res)):
res_str=res_str+res[i]
return res_str
print(longestPalindrome(array1))
时间复杂度:两层循环 O(n²)。
空间复杂度: O(n)。
执行用时 3060 ms
内存消耗21.6 MB
解法六:中心扩展法
array1=list(i for i in input().split())
print(array1)
#array2=list(i for i in input().split())
def expandAroundCenter(s,i,j):
"""
找出回文子串,返回其长度
"""
L,R=i,j
while(L>=0 and R<len(s) and s[L]==s[R]):
L-=1
R+=1
return R-L-1
def longestPalindrome(s):
if s==None:
return None
else:
start=0
end=0
for i in range(len(s)):
len1=expandAroundCenter(s,i,i)
len2=expandAroundCenter(s,i,i+1)
len3=max(len1,len2)
if len3>end-start:
start=i-(len3-1)//2
end=i+len3//2
return s[start:end+1]
print(longestPalindrome(array1))
时间复杂度:O(n²)。
空间复杂度:O(1)。
执行用时1276ms
内存消耗13.8 MB
解法七: Manacher’s Algorithm 马拉车算法。
扩展:
反转列表的三种方法
print("====第一种====")
a=[1,2,3,4,5]
a.reverse()
print(a)
print("====第二种====")
b=[1,2,3,4,5]
b_reverse=list(reversed(b))
print(b_reverse)
print("====第三种====")
c=[1,2,3,4,5]
c_reverse=c[::-1]
print(c_reverse)
输出:
====第一种====
[5, 4, 3, 2, 1]
====第二种====
[5, 4, 3, 2, 1]
====第三种====
[5, 4, 3, 2, 1]
二维数组赋值问题
m=5,n=6
a=[[0]*n]*m
上述代码为生成一个m行n列的矩阵,但需要注意的是,当改变其中一个值时,该值所在列都会被改变。
欲使其独立变化,则需要初始化如下:
a=[[0]*n for _ in range(m)]