返回

LeetCode 53:动态规划寻觅最大子数组和(Swift)

IOS

LeetCode 53 是一个算法题,旨在寻找给定数组中具有最大和的连续子数组。虽然乍一看似乎是一项艰巨的任务,但借助动态规划,我们可以巧妙地分解问题,逐步求解。

动态规划 是一种自顶向下法,它将问题分解为更小的子问题,逐层解决,最终得到整体解决方案。对于 LeetCode 53,我们将使用一个大小为 n(数组长度)的动态规划表,其中 n[i] 表示以第 i 个元素结尾的连续子数组的最大和。

初始化:

我们首先初始化动态规划表的第一项为 nums[0],表示长度为 1 的子数组的最大和,即第一个元素本身。

dp[0] = nums[0]

递推公式:

接下来,我们将使用一个循环逐个遍历剩余的元素,并根据当前元素和前一个元素的最大和来更新动态规划表:

for i in 1..<nums.count {
  dp[i] = max(nums[i], dp[i - 1] + nums[i])
}

这个递推公式的核心思想是:以第 i 个元素结尾的连续子数组的最大和要么是该元素本身(当之前子数组的和为负数时),要么是前一个元素的最大和加上该元素(当之前子数组的和为正数时)。

求解:

循环完成后,动态规划表中的最后一个元素即为所求的具有最大和的连续子数组的和。

let maxSum = dp[nums.count - 1]

示例:

考虑数组 nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4],我们使用动态规划表逐步计算:

Index Value
0 -2
1 1
2 -3
3 4
4 3
5 5
6 6
7 1
8 5

最大和为 6,位于从索引 3 到 6 的子数组 [-3, 4, -1, 2, 1] 中。

Swift 实现:

func maxSubArray(_ nums: [Int]) -> Int {
    var dp = Array(repeating: 0, count: nums.count)
    dp[0] = nums[0]
    
    for i in 1..<nums.count {
        dp[i] = max(nums[i], dp[i - 1] + nums[i])
    }
    
    return dp[nums.count - 1]
}