leetcode
# 最长回文子串 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)