# 最长回文子串
class Solution:
def longestPalindrome(self, s: str) -> str:
return self.manacher(s)
@staticmethod
def manacher(s: str) -> str:
# 如果s是单字符的字符串,那么直接返回
if len(s) < 2:
return s
# 将一个可能是偶数长/奇数长的字符串,首位以及每个字符间添加#,确保添加后变成了长度为奇数的字符串
manacher_length = len(s) * 2 + 1
manacher_str = "#".join(s).center(manacher_length, "#")
# 记录最长子回文串
max_palindrome = ""
for i in range(manacher_length):
left = i - 1
right = i + 1
while left >= 0 and right < manacher_length and \
manacher_str[left] == manacher_str[right]:
left -= 1
right += 1
# 将左右指针回退一位,得到本次遍历的回文串长度:(right - 1) - (left + 1) + 1 = right - left - 1
if right - left - 1 > len(max_palindrome):
max_palindrome = manacher_str[left + 1:right]
# 由于max_palindrom是包含特殊字符#的回文子串,因此需要将#字符删除后返回
return max_palindrome.replace("#", "")
# 自测用例
if __name__ == '__main__':
s = Solution()
result = s.longestPalindrome("abcbcba")
print(result)
# 最长无重复子串
def longest_str(str):
str_dict = {}
start = 0
res = ""
for i in range(len(str)):
if str[i] in str_dict:
start = max(start, str_dict[str[i]] + 1)
str_dict[str[i]] = i
if len(str[start:i+1])>len(res):
res = str[start:i+1]
return res
print(longest_str("abcdcabcde"))
# 最大子数组和
def max_sum(arr):
dp = [0] * len(arr)
dp[0] = arr[0]
for i in range(1, len(arr)):
dp[i] = max(arr[i], dp[i-1]+arr[i])
return max(dp)
# 最大子数组乘积
def max_multi(arr):
dp_max = [0]*len(arr)
dp_min = [0]*len(arr)
dp_max[0] = arr[0]
dp_min[0] = arr[0]
for i in range(1,len(arr)):
dp_min[i] = min(arr[i], arr[i]*dp_min[i-1])
dp_max[i] = max(arr[i], arr[i]*dp_max[i-1], arr[i]*dp_min[i-1])
return max(dp_max)
print(max_multi([2,3,-2,4]))
# 组合总和
class Solution:
def combinationSum(self, candidates, target):
result = []
self.DFS(candidates, [], target,result)
return result
def DFS(self,candidates, path, target,result):
# 不符合,结束
if sum(path)>target:
return
# 这是DFS的边界控制条件,当 路径和等于目标时,说明这个路径是我们所需要的。直接附加到结果即可。
if sum(path) == target:
result.append(path[:])
return
# 相同的套路,对DFS下的所有路径进行遍历呗,进行往path路径上的附加。
for i in range(len(candidates)):
# 如果dfs的是candidates的话,就是全排列
# 如果从index开始的数组,即下一次dfs是从他自己开始,就是去重复的数组,就是前边考虑过的数,不再考虑了
# 如果从index+1开始的话,就是没有重复数字的去重数组
path.append(candidates[i])
self.DFS(candidates[i:], path,target,result)
# 在DFS递归最后,进行一定的还原
path.pop()
aa = Solution()
print(aa.combinationSum([2,3,6,7], 7))
# 组合
class Solution:
#主函数,这里会启动DFS的 组合搜索
def permute(self, nums):
result=[]
l=len(nums)
self.DFS(nums,[],result,l)
return result
#
def DFS(self,nums,path,result,l):
#这是 拼接成功的 标识,当拼接成功时,说明是一个成功的 DFS遍历得到的结果。 path中存储中的当做真实的拼接来用即可。
if len(path)==l:
result.append(path[:])
return
#这里是针对数组 进行拼接角度的DFS遍历
for i in range(len(nums)):
path.append(nums[i])
self.DFS(nums[:i]+nums[i+1:],path,result,l)
#DFS最核心的一点是 一定要进行还原,这样才能轻量化,path内的信息才是每次构建时所需要的。
path.pop()
aa = Solution()
print(aa.permute([2,3,6]))
def quick_sort(alist, start, end):
"""快速排序"""
if start >= end: # 递归的退出条件
return
mid = alist[start] # 设定起始的基准元素
low = start # low为序列左边在开始位置的由左向右移动的游标
high = end # high为序列右边末尾位置的由右向左移动的游标
while low < high:
# 如果low与high未重合,high(右边)指向的元素大于等于基准元素,则high向左移动
while low < high and alist[high] >= mid:
high -= 1
alist[low] = alist[high] # 走到此位置时high指向一个比基准元素小的元素,将high指向的元素放到low的位置上,此时high指向的位置空着,接下来移动low找到符合条件的元素放在此处
# 如果low与high未重合,low指向的元素比基准元素小,则low向右移动
while low < high and alist[low] < mid:
low += 1
alist[high] = alist[low] # 此时low指向一个比基准元素大的元素,将low指向的元素放到high空着的位置上,此时low指向的位置空着,之后进行下一次循环,将high找到符合条件的元素填到此处
# 退出循环后,low与high重合,此时所指位置为基准元素的正确位置,左边的元素都比基准元素小,右边的元素都比基准元素大
alist[low] = mid # 将基准元素放到该位置,
# 对基准元素左边的子序列进行快速排序
quick_sort(alist, start, low - 1) # start :0 low -1 原基准元素靠左边一位
# 对基准元素右边的子序列进行快速排序
quick_sort(alist, low + 1, end) # low+1 : 原基准元素靠右一位 end: 最后
if __name__ == '__main__':
alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
quick_sort(alist, 0, len(alist) - 1)
print(alist)