最大子数组和(Maximum Subarray)

📌 定义

最大子数组和问题是指:给定一个整数数组,找到一个具有最大和的连续子数组(至少包含一个元素),返回其最大和。

数组: [-2, 1, -3, 4, -1, 2, 1, -5, 4]
最大子数组: [4, -1, 2, 1]
最大和: 6

🎯 解法对比

方法时间复杂度空间复杂度说明
暴力枚举O(n³)O(1)三层循环
优化枚举O(n²)O(1)两层循环+累加
分治法O(n log n)O(log n)本文重点
动态规划O(n)O(1)最优解

💡 分治法核心思想

将数组从中间分成左右两部分,最大子数组和只可能出现在三种情况:

  1. 左半部分:完全在左边
  2. 右半部分:完全在右边
  3. 跨越中点:横跨左右两边
数组: [-2, 1, -3, 4, -1, 2, 1, -5, 4]
                  ↑
                 中点

情况1: 左半部分最大和 = 1
情况2: 右半部分最大和 = 6 ([4,-1,2,1])
情况3: 跨越中点最大和 = 5 ([4,-1,2,1])

取最大值 = 6

Go 代码

Go 实现

package main
 
import (
    "fmt"
    "math"
)
 
func maxSubArrayDivide(nums []int) int {
    return helper(nums, 0, len(nums)-1)
}
 
func helper(nums []int, left, right int) int {
    if left == right {
        return nums[left]
    }
 
    mid := (left + right) / 2
 
    leftMax := helper(nums, left, mid)
    rightMax := helper(nums, mid+1, right)
    crossMax := crossSum(nums, left, right, mid)
 
    return max(leftMax, max(rightMax, crossMax))
}
 
func crossSum(nums []int, left, right, mid int) int {
    leftSum := math.MinInt32
    currSum := 0
    for i := mid; i >= left; i-- {
        currSum += nums[i]
        if currSum > leftSum {
            leftSum = currSum
        }
    }
 
    rightSum := math.MinInt32
    currSum = 0
    for i := mid + 1; i <= right; i++ {
        currSum += nums[i]
        if currSum > rightSum {
            rightSum = currSum
        }
    }
 
    return leftSum + rightSum
}
 
func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}
 
func main() {
    nums := []int{-2, 1, -3, 4, -1, 2, 1, -5, 4}
    fmt.Printf("最大子数组和: %d\n", maxSubArrayDivide(nums))
}

思路展开

分治法的递归树

原数组: [-2, 1, -3, 4, -1, 2, 1, -5, 4]

                    [-2,1,-3,4,-1,2,1,-5,4]
                    /                      \
          [-2,1,-3,4,-1]              [2,1,-5,4]
          /            \               /        \
    [-2,1,-3]      [4,-1]         [2,1]      [-5,4]
     /    \         /  \           /  \       /  \
[-2,1]  [-3]    [4] [-1]       [2] [1]   [-5] [4]
 / \
[-2][1]

深度:O(log n)
每层时间:O(n)
总时间:O(n log n)

跨越中点的计算

数组: [4, -1, 2, 1]
中点: 在-1和2之间

从中点向左: 4, -1 → 左边最大和 = 4 + (-1) = 3
从中点向右: 2, 1  → 右边最大和 = 2 + 1 = 3

跨越中点的最大和 = 3 + 3 = 6

经典题目

基础应用

变体

2D扩展

  • 最大子矩阵和
  • 最大正方形

⚖️ 优缺点

分治法

优点:

  • ✅ 展示分治思想
  • ✅ 可扩展到2D问题

缺点:

  • ❌ 时间复杂度O(n log n)不是最优
  • ❌ 需要额外的栈空间

动态规划(Kadane算法)

优点:

  • ✅ 时间复杂度O(n)
  • ✅ 空间复杂度O(1)
  • ✅ 代码简洁

缺点:

  • ❌ 不易扩展到2D

🎨 应用场景

  1. 股票交易:找最佳买卖时机
  2. 图像处理:找最亮区域
  3. 信号处理:找最强信号段
  4. 数据分析:找最优时间窗口

💡 相关问题

相关主题


返回:分治算法 | 算法学习导航