1.Two Sum问题,给定一个数组 nums找到数组中两个数之和为给定值所有或者(找到即可)组合。
暴力搜索效率很低,这里用类似双指针可以让时间复杂度达到O(N)
def two_sum(nums, target): res = [] nums.sort() if len(nums) < 2: return res elif nums[0] >= target: return res else: begin = 0 end = len(nums)-1 while begin < end: if nums[begin] + nums[end] == target: temp = [nums[begin], nums[end]] res.append(temp) begin += 1; end -= 1 elif nums[begin] + nums[end] > target: end -= 1 else: begin += 1 return res nums = [1, 3, -2, 0, 5, 4, 6, 4, 7] target = 9 print(two_sum(nums, target))
还有利用python里的字典来解决的(这里返回的是索引,当然也可以返回具体的值,不太明白这里的复杂度是多少):
def twoSum(num, target): dict = {} for i in range(len(num)): x = num[i] if target - x in dict: return (dict[target - x], i) dict[x] = i num = [-3,-2,0,1,2,4,5,7,-1] print(twoSum(num, 12))
2. threesum问题:
def threeSum(nums): res = [] length=len(nums) if length<3:return res nums.sort() for i in range(length): if nums[i]>0:break if i>0 and nums[i]==nums[i-1]:continue begin=i+1;end=length-1 while begin < end: sum=nums[i]+nums[begin]+nums[end] if sum==0: tmp=[nums[i],nums[begin],nums[end]] res.append(tmp) begin+=1;end-=1 while begin < end and nums[begin] == nums[begin - 1]: begin += 1 while begin < end and nums[end] == nums[end + 1]: end -= 1 elif sum>0:end-=1 else:begin+=1 return res nums = [-1,0,1,7,-6,3,5] print(threeSum(nums))
更新threeSum问题:(指定一个数,然后用两个指针类似于二分查找)
def threeSum(nums): ans = [] nums.sort() for i in range(len(nums) - 2): if i == 0 or nums[i] > nums[i - 1]: # 如果后个和前个相等,那么后一个能实现相加为target必然和前面重复 left = i + 1 right = len(nums) - 1 while left < right: target = nums[left] + nums[right] + nums[i] if target == 0: ans.append([nums[i], nums[left], nums[right]]) left += 1 right -= 1 while left < right and nums[left] == nums[left-1]: # skip duplicates left += 1 #两个while也体现了一点点分治 while left < right and nums[right] == nums[right+1]:#这两个while可以一直跳转到最后的 right -= 1 #数的位置如[-2,0,0,2,2]跳转到3,2 elif target < 0: #注意while最后的状态是第一个不满足条件的位置 left += 1 else: right -= 1 return ans
3. 最长递增子序列问题:
用贪心的思想:(从前往后,每个数做标记,当前数上的标记为前面比他小的数上最大标记+1,很容易理解,这样延伸到当前数时可保证是最长的递增序列)代码如下:
def dp(nums): d = [0] re = [[0] for k in nums] for i in range(1, len(nums)): for j in range(i): if nums[j] < nums[i]: re[i].append(d[j]+1) d.append(max(re[i])) return max(d)+1 nums = [1,3,2,4] print(dp(nums))
用动态规划来做:
4. 求字符串最长回文子串的长度(回文子串即是对称的连续子串)中心展开法,考虑bb这种所以每个字符插入‘#’:
def func(arr): re = [] new_arr = '' for i in arr: new_arr += i+'#' for i in range(2, len(new_arr)-2, 2): j = 1 count = 0 while i-j >= 0 and i+j <= len(new_arr)-1: if new_arr[i-j] == new_arr[i+j]: count += 1 j += 1 else: break re.append(count) return max(re)+1 arr = 'cabacd' print(func(arr))