53. 最大子数组和

115 阅读2分钟

「这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战」。

题目描述

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

子数组 是数组中的一个连续部分。

 

示例 1:

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

思路分析

首先,既然是求连续子数组的和,那可以使用前缀和。 (当然可能这道题也可以使用滑动窗口来解决)

通过前缀和求出前缀和数组。时间复杂度O(n)

当起点i不为0时求arr[i] ~ arr[j]的数组和为sums[j] - sums[i - 1]

首先讨论是否存在以i起点遍历j求出最大子数组和为k后,是否会出现起点大于i但是终点小于j且子数组和大于k的情况。

假设存在这种情况那么相当于以i为起点,以i' - 1为终点的值为负数。那么我们仅需要在这种情况时直接break即可。

具体代码

public:
    int maxSubArray(vector<int>& nums) {
        if(nums.size() == 1)return nums[0];
        // vector<int> sums(nums.size() + 1);
        // sums[0] = 0;
        int ret = nums[0];
        // for(int i = 1; i < nums.size() + 1; i++){
        //     sums[i] = sums[i - 1] + nums[i - 1];
        // }
        int j = 0;
        for(int i = 0; i < nums.size(); ){
            int sum = 0;
            while(sum >= 0 && j < nums.size()){
                sum += nums[j++];
                ret = max(ret, sum);
            }
            if(j == nums.size())break;
            i = max(j, i + 1);
            j = i;
        }
        return ret;
    }
};

总结

实现的时候发现根本用不上前缀和,因为求和的次数很低,双指针滑动窗口只需要遍历两次ij即可,直接双指针就可以了。

双指针时调试指针求和的时候花了很多时间,对于while的条件,i的遍历方式,都是基于题现给出的答案,理论上应该是缺少一套现成的模板。