算法_贪心算法_最大子数组和

最大子数组和

leetcode链接

两种解法

暴力

最直观的方法就是使用暴力来遍历区间的开头和结尾,然后对区间求和,取最大值。如果对暴力方法优化的话,可以固定区间开头为0,然后遍历区间结尾,对每个区间求和,然后通过这些区间之间做减法可以得到不同开头的区间的和,再进行比较。

举例:
nums = [1,2,3,4]

先求出区间[0,0],[0,1],[0,2],[0,3]的和,分别为1,3,6,10,然后如果想求区间[1,2]的和,就可以用区间[0,2]-[0,0],即为6-1=5。这样只需要遍历求一次和,并记录下来就可以了,时间复杂度会降低一些。

贪心

贪心策略:

首先,考虑一种极端情况,序列上的数字都是大于等于0的整数,那么最大子数组和就是该数组的总和。那么为什么会产生分歧呢?就是因为序列上有可能出现负数,所以我们来特殊考虑一下遇到负数的情况

首先,如果从头对区间求和,那么每次遇到负数(假设该负数的位置为index),就表示区间[0,index-1]的和一定要比区间[0,index]的和要大

这种情况下,我们要考虑两种情况:

首先声明一个result,保存结果,初始化为一个很小很小的值。

  1. 如果遇到负数了,并且区间[0,index]的和是负数,那么就要比较一下[0,index-1]的和和result的值,保留较大的。并且将开头修改到从index+1位置往后第一个不是负数的数(假设该位置为index2)。

    原因:因为区间[0,index-1]和为正,区间[0,index]和为负,区间[index+1,index2-1]为负,区间[index2,index2+n]为正(n为到下一个负数位置的距离,n可能取0,即只有index2位置的这一个数),所以只要保存下区间[0,index-1]的值,然后和后面的区间[index2,index2+n]的值作比较即可。

  2. 如果遇到负数了,并且区间[0,index]的和是正数,那么就还有可能构成最大子数组和,所以只需要比较一下[0,index]和result,保留较大值,继续向后遍历即可。

为了代码能够简洁,我们可以再分析一下遇到正数的情况:

  1. 遇到正数,则还有可能构成最大子数组和,所以只需比较当前区间和和result,保留较大值,然后继续向后遍历即可。

我们发现,遇到正数和遇到负数并且区间[0,index]的操作方法一样,所以区别这三种情况可以用 [0,index]之和是否为负 为标准来区分为两种情况。

  1. [0,index]之和为负,则比较当前[0,index]之和和result,保留较大值,然后找到下一个不为负的值做开头,继续向后遍历。
  2. [0,index]之和为正,则比较当前区间之和和result,保留较大值,然后继续向后遍历。

贪心“贪”在:如果遇到区间和为负了,就立刻抛弃,然后找下一个区间。

代码如下:

def maxSubArray(nums):
    count = 0 # 记录区间和
    result = float('-inf') # 初始化为一个很小很小的值
    for i in range(len(nums)):
        count += nums[i]
        if count>result: # 比较区间和 和 result,保留较大的
            result = count
        if count<0: # 如果区间和为负,则要找到新的起始位置,此时需要把之前统计的区间和变为0
            count = 0

    return result
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值