LeetCode.53.-最大子数组和-贪心算法(Swift)

271 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情 。如果哪里写的不对,请大家评论批评。

最大子数组和

题目

给你一个整数数组 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. 从左向右去遍历,一个数一个数的相加,如果当前sum<0,重置sum=0,重新开始找子数组
  2. 举例:[-2,1,-3,4,-1,2,1,-5,4]
  3. 定义一个max_num来记录最终的结果,初始化的时候为极小数,一个cur_num来记录当前子数组的和
  4. 从左向右开始第一位-2cur_num = -2 + cur_num = -2max_num = max(max_num,-2),所以max_num暂存-2(也是为了预防数组就一个-2的值)最大子数组和.drawio.png
  5. 因为前一个-2 < 0,所以放弃原来的值cur_num = 0,这时候值为1,cur_num = -1 + cur_num = 1,,max_num也是保存最大的值max_num = max(-2,1) = 1 最大子数组和.drawio (1).png
  6. -3,cur_num = -3 + cur_num = -2,,max_num也是保存最大的值max_num = max(-2,1) = 1,然后 cur_num=-2 < 0, 所以cur_num = 0最大子数组和.drawio (2).png
  7. 4,cur_num = 4 + cur_num = 4,,max_num也是保存最大的值max_num = max(4,1) = 4,然后 cur_num=4 > 0, 所以cur_num = 4最大子数组和.drawio (3).png
  8. -1,cur_num = -1 + cur_num = 3,,max_num也是保存最大的值max_num = max(3,4) = 4,然后 cur_num=3 > 0, 所以cur_num = 3最大子数组和.drawio (4).png
  9. 2,cur_num = 2 + cur_num = 5,,max_num也是保存最大的值max_num = max(5,4) = 5,然后 cur_num=5 > 0, 所以cur_num = 5最大子数组和.drawio (5).png
  10. 1,cur_num = 1 + cur_num = 6,,max_num也是保存最大的值max_num = max(6,5) = 6,然后 cur_num=6 > 0, 所以cur_num = 6最大子数组和.drawio (6).png
  11. -5,cur_num = -5 + cur_num = 1,,max_num也是保存最大的值max_num = max(1,6) = 6,然后 cur_num=1 > 0, 所以cur_num = 1最大子数组和.drawio (7).png
  12. 4,cur_num = 4 + cur_num = 5,,max_num也是保存最大的值max_num = max(5,6) = 6,然后 cur_num=5 > 0, 所以cur_num = 5最大子数组和.drawio (8).png

代码

class Solution {
    func maxSubArray(_ nums: [Int]) -> Int {
        // 如果数组为nil,没有意义
        guard nums.count > 0 else {
            return 0
        }
        // 记录当前的和
        var cur_num = 0
        // 记录最大值,为了防止数组全是负数,初始化给出最小值
        var max_num = Int.min
        for value in nums {
            // 当前累计的和
            cur_num = cur_num+value
            // 累计的和,保存的最大值,取最大
            max_num = max(max_num, cur_num)
            // 如果当前和小于0,没有相加的意义
            if cur_num < 0 {
                cur_num = 0
            }
        }
        return max_num
    }
}