「这是我参与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的遍历方式,都是基于题现给出的答案,理论上应该是缺少一套现成的模板。