53. 最大子数组和

82 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

一、题目描述:

53. 最大子数组和 - 力扣(LeetCode) (leetcode-cn.com)

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

输入:nums = [1]
输出:1

示例 3:

输入:nums = [5,4,-1,7,8]
输出:23

提示

  • 1 <= nums.length <= 10^5
  • -10^4 <= nums[i] <= 10……4  

进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。

二、思路分析:

用了分治法,代码写的很粗糙,简单的说一下思路
数组中最大的子数组和,如果把数组一分为二,这个和的出现位置无非三种:\

  1. 最大子数组和全部在左边
  2. 最大子数组和全部在右边
  3. 最大子数组和跨越中点

可以注意到第一种和第二种方法能够递归实现,第三种方法需要单个列出
由此能够体现分治法把原问题分解为若干个子问题,并且能够递归的求解这些子问题
最后能将子问题合并为一个新的解(在这里第三种情况相当于合并过程),层层递归解出答案\

定义了Crossing(nums)函数,用来处理上述的第三种方法,由于是跨越中点最大子数组和
必定包括mid(中点所在位置)点,用了两次循环,第一次遍历的求解从中间到左边开头的最大和
第二次遍历的求解从中间到右边的最大和,最后将两个相加便得到跨越中点最大和\

fenzhi(nums)函数便是分治法主函数
基本情况 :当数组长度小于等于1,说明最多有1个元素,返回该元素
递归情况 : 每次将数组一分为二,记录每次的左边最大和,右边最大和,跨越中点最大和,并返回其中较大者
不断递归得到答案

三、AC 代码:

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        def Crossing(nums):
            mid = len(nums) //2
            i = mid-1
            LeftSum =-float("inf")  #此为负无穷
            ThisSum = 0
            RightSum = -float("inf") #此为负无穷
            while(i>=0):
                ThisSum += nums[i]
                if(ThisSum>LeftSum):
                    LeftSum = ThisSum
                i-=1
            i = mid 
            ThisSum = 0
            while(i<len(nums)):
                ThisSum += nums[i]
                if ThisSum >RightSum :
                    RightSum = ThisSum
                i+=1
            return (LeftSum + RightSum)
        
        def fenzhi(nums):
            if len(nums) <= 1:
                return nums[0]
            else :
                mid = len(nums) // 2
                LeftSum = fenzhi(nums[0:mid])
                RightSum = fenzhi(nums[mid:])
                CrossingSum = Crossing(nums)
                if(CrossingSum>=RightSum and CrossingSum >=LeftSum) :
                    return CrossingSum
                elif (LeftSum>=RightSum and LeftSum >=CrossingSum):
                    return LeftSum
                elif (RightSum>=LeftSum and RightSum >=CrossingSum):
                    return RightSum
        return fenzhi(nums)