【力扣-贪心】3、最大子序和(53)

208 阅读2分钟

「这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战

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;
    }
};