> For the complete documentation index, see [llms.txt](https://kerasnoone.gitbook.io/garnet/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kerasnoone.gitbook.io/garnet/suan-fa/fen-zhi/53-zui-da-zi-xu-he.md).

# \[53]\[简单]\[动态规划]\[分治] 最大子序和

## 题目描述

[53. 最大子序和](https://leetcode-cn.com/problems/maximum-subarray/) [剑指 Offer 42. 连续子数组的最大和](https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/)

给定一个整数数组 nums ，找到一个具有最大和的连续子数组（子数组最少包含一个元素），返回其最大和。

示例:

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

进阶:

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

## 解题思路

[解题思路: 最大子序和](https://leetcode-cn.com/problems/maximum-subarray/solution/zui-da-zi-xu-he-by-leetcode-solution/)

### 动态规划

用$$f(i)$$状态表示以第$$i$$个数结尾的**连续子数组的最大和**, 显然最后的结果就是$$\max{f(i)}$$.

以第$$i$$个数的角度考虑, 如果能与前一位连在一起, 要求前一位$$f(i-1)$$必须不小于0, 否则与前面相加会变小, 肯定不会是连续最大和对应子数组的一部分. 如果第$$i$$个数是后续某个数连续最大和对应的子序列的一部分, 那肯定是不包含$$i$$之前的部分.

因此对应的状态转移方程为:

$$f(i)=\max{f(i-1)+a\_i, a\_i}$$

得到一个时间复杂度为$$O(n)$$, 空间复杂度为$$O(n)$$的算法.

可以使用**滚动数组**思想, 进一步节省空间. 由于每一步只使用上一步的结果, 因此只要保存上一步的$$f$$即可, 空间复杂度压缩为$$O(1)$$.

```python
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        n = len(nums)
        if n == 0:
            return 0

        a, total = -1e12, -1e12
        for num in nums:
            a = max(num + a, num)
            total = max(a, total)
        return total
```

### 分治

分治的思路参考[解题思路: 最大子序和](https://leetcode-cn.com/problems/maximum-subarray/solution/zui-da-zi-xu-he-by-leetcode-solution/)中的方法二.

```python
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        n = len(nums)
        if n == 0:
            return 0
        l, r, m, s = self.sub_array(nums, 0, n - 1)
        return m

    def sub_array(self, array, start, end):
        if start == end:
            t = array[start]
            return t, t, t, t  # left, right, max, sum

        mid = (start + end) // 2
        ll, lr, lm, ls = self.sub_array(array, start, mid)
        rl, rr, rm, rs = self.sub_array(array, mid + 1, end)
        l = max(ll, ls + rl)
        r = max(rr, rs + lr)
        m = max([lm, rm, lr + rl])
        s = ls + rs
        return l, r, m, s
```
