题目
给定一个整数数组,找出和最大的连续子数组(至少包含一个元素)并返回最大和。
尝试使用分治算法实现
思路
参考了《算法导论》里关于分治的讲解,正好就是这个题目,不过它的方法比较细致,把最大子数组的位置也求出来了。这道题只要求最大和,我简化了一下。思路是把数组从中间分成两部分,最大子数组要么是左半部分,要么是右半部分,要么是跨越中点,包含左右两个部分。递归比较各层的这三个部分的最大子数组和。
代码
class Solution:
def find_max_crossing_subarray(self, left, right):
left_sum, right_sum = float('-inf'), float('-inf')
sum_nums = 0
for i in range(len(left) - 1, -1, -1):
sum_nums += left[i]
if sum_nums > left_sum:
left_sum = sum_nums
sum_nums = 0
for i in range(0, len(right), 1):
sum_nums += right[i]
if sum_nums > right_sum:
right_sum = sum_nums
return left_sum + right_sum
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
len_nums = len(nums)
if len_nums == 1:
return nums[0]
mid = len_nums // 2
left_sum = self.maxSubArray(nums[:mid])
right_sum = self.maxSubArray(nums[mid:])
cross_sum = self.find_max_crossing_subarray(nums[:mid], nums[mid:])
return max(left_sum, right_sum, cross_sum)
其他
这道题想了挺长时间,解之前把归并排序重新写了一遍,更简洁优雅一些。
def merge(left, right):
result = []
while left and right:
result.append(left.pop(0) if left[0] < right[0] else right.pop(0))
result += left + right
return result
def merge_sort(target):
len_target = len(target)
if len_target == 1:
return target
mid = len_target // 2
left, right = target[:mid], target[mid:]
return merge(merge_sort(left), merge_sort(right))