​​53. 最大子序和​​

题目描述

给定一个整数数组 ​​nums​​ ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例 1:

输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

输入: nums = [1]
输出: 1

示例 3:

输入: nums = [0]
输出: 0

示例 4:

输入: nums = [-1]
输出: -1

示例 5:

输入: nums = [-100000]
输出: -100000

暴力法

  • 两层for循环进行累加
  • 第一层for循环控制开始的位置
  • 第二层for循环将从开始位置的数一直累加到最后一个元素,并且记录累加和的最大值
  • 结果:测试用例数据量太大,在​​leetcode​​超出时间限制

代码

class Solution
{
public:
int maxSubArray(vector<int> &nums)
{
// 记录结果
int result = -65536;
// 记录和
int count;
// 从第一个元素开始遍历
for (int i = 0; i < nums.size(); i++)
{
// 从第i个元素开始,计算累加到最后一个元素的和
count = 0;
for (int j = i; j < nums.size(); j++)
{
count += nums[j];
result = count > result ? count : result;
}
}
return result;
}
};

贪心算法

在求和的过程中,如果起始节点为负数,可以将此数跳过,因为将此数计算到结果中,只会拉低总和。下面考虑贪心的过程: 局部最优的情况下,记录最大的累加和,可推出全局最优解

  • 局部最优:当累加和为负数时,就可以舍弃本次累加。从下一个元素开重新计算累加和。
  • 全局最优:选取最大的累加和
// 时间复杂度:O(n) 空间复杂度:O(1)
#define INT_MAX 2147483647
#define INT_MIN (-INT_MAX - 1)
class Solution {
public:
int maxSubArray(vector<int>& nums) {
// 记录最终结果
int result = INT32_MIN;
// 记录每段元素的累加和
int count = 0;
for (int i = 0; i < nums.size(); i++) {
count += nums[i];
// 取区间累计的最大值(相当于不断确定最大子序终止位置)
if (count > result) {
result = count;
}
// 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和
if (count <= 0) count = 0;
}
return result;
}
};