力扣53题:最大子数组和-新手教程
题目分析与解读
题目要求:给定一个整数数组nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
关键点解析:?
子数组?:必须是原数组中连续的元素序列
最大和?:所有可能的连续子数组中,和最大的那个
最少包含一个元素?:即使所有数都是负数,也要选一个最大的负数
容易混淆的地方:?
不是求整个数组的和,而是求其中一段连续元素的和
子数组不能跳跃选取元素,必须是连续的
当数组全为负数时,最大子数组和就是最大的那个负数
现实生活场景类比
想象你是一个股票投资者,记录每天股票的涨跌(正数表示涨,负数表示跌)。你想知道在哪一段连续的时间内买入和卖出能获得最大收益。
例如:
数组:[7,-3,4,-1,2,-5]
对应股票:第一天涨7元,第二天跌3元,第三天涨4元...
最大收益区间:第1天到第5天(7-3+4-1+2=9元)
解题步骤详解
初始化?:设第一个元素为当前和(sum)和最大和(maxsum)
遍历数组?:从第二个元素开始
计算当前元素与之前和的和:如果之前和是负数,就舍弃(因为负数会减小总和),从当前元素重新开始;如果是正数,就继续累加
比较当前和与最大和,更新最大和
返回结果?:遍历结束后,maxsum就是最大子数组和
注意事项
数组可能全为负数,此时最大和就是最大的那个负数
需要至少遍历一次整个数组,时间复杂度O(n)
空间复杂度O(1),只用了常数个额外空间
注意边界条件:空数组(题目保证至少一个元素)
初始值设置很重要,不能初始化为0,因为可能有负数
代码实现与注释
classSolution{
public:
intmaxSubArray(vectorintnums){
intsum=nums[0];//当前子数组和,初始为第一个元素
intmaxsum=sum;//最大子数组和,初始为第一个元素
for(inti=1;inums.size();i++){
//如果之前的sum是负数,就从当前元素重新开始(因为负数会减小总和)
//如果是正数,就继续累加
sum=nums[i]+max(sum,0);
//更新最大和
if(summaxsum){
maxsum=sum;
}
}
returnmaxsum;
}
};
问题与代码分析
算法分析:?
这个解法使用了Kadane算法(卡登算法),是解决最大子数组和问题的最优解法。它的核心思想是动态规划:每一步都做出在当前看来最好的选择(局部最优),最终得到全局最优解。
代码亮点:?
简洁高效:时间复杂度O(n),空间复杂度O(1)
使用max(sum,0)巧妙处理了是否舍弃之前子数组的问题
初始值设置合理,考虑了全负数的情况
可能的变体:?
如果需要返回最大子数组的起始和结束位置,可以记录索引
如果数组很大,可以考虑分治法(虽然时间复杂度相同)
如果允许子数组为空(和为0),需要修改初始条件
这个算法在实际中有广泛应用,如金融分析、信号处理等领域,凡是需要在一系列连续数据中寻找最优片段的问题都可以考虑这种思路。