leetcode 53. Maximum Subarray 最大子数组 分治算法

题目

给定一个整数数组,找出和最大的连续子数组(至少包含一个元素)并返回最大和。

尝试使用分治算法实现

思路

参考了《算法导论》里关于分治的讲解,正好就是这个题目,不过它的方法比较细致,把最大子数组的位置也求出来了。这道题只要求最大和,我简化了一下。思路是把数组从中间分成两部分,最大子数组要么是左半部分,要么是右半部分,要么是跨越中点,包含左右两个部分。递归比较各层的这三个部分的最大子数组和。

代码

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))

猜你喜欢

转载自blog.csdn.net/qq_35753140/article/details/83962469