版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/majichen95/article/details/81735492
给定一个整数数组,找出两个 不重叠 子数组使得它们的和最大。
每个子数组的数字在数组中的位置应该是连续的。
返回最大的和。
样例
给出数组 [1, 3, -1, 2, -1, 2]
这两个子数组分别为 [1, 3]
和 [2, -1, 2]
或者 [1, 3, -1, 2]
和 [2]
,它们的最大和都是 7
挑战
要求时间复杂度为 O(n)
注意事项
子数组最少包含一个数
解题思路1:
既然在上一题Lintcode 41:Maximum Subarray已经可以求出整个数组的最大和子数组,那么这个题目就是增加了一条分界线,求分界线左右两边的子数组的最大和相加,很容易想到:遍历分界线,依次求取分界线两端的最大和。这样做的时间复杂度为O(n^2),代码如下:
class Solution {
public:
/*
* @param nums: A list of integers
* @return: An integer denotes the sum of max two non-overlapping subarrays
*/
int maxTwoSubArrays(vector<int> &nums)
{
// write your code here
int res = INT_MIN;
for(int i=0 ; i+1 < nums.size() ; i++)
{
int max1 = maxSubArrays(nums , 0 , i);//求nums[0..i]的最大子数组和
int max2 = maxSubArrays(nums , i+1 , nums.size()-1);//求nums[i+1...nums.size()-1]的最大子数组和
int temp = max1 + max2;
res = res > temp ? res : temp;
}
return res;
}
//求nums[l...r]之间最大子数组和
int maxSubArrays(vector<int> & nums , int l , int r)
{
int max = nums[l];
int temp = 0;
for(int i = l ; i <= r ; i++)
{
temp += nums[i];
max = max > temp ? max : temp;
if(temp < 0)
temp = 0;
}
return max;
}
};
解题思路2:
同样是上面的思路,但是利用空间换时间的方式,先从左向右遍历,将左边子数组所有最大和保存在一个数组中,再从右向左遍历,将右边子数组所有最大和保存在另一个数组中,最后将两个数组彼此不相交的位置进行相加即可。这样做的时间复杂度为O(n).
class Solution {
public:
/*
* @param nums: A list of integers
* @return: An integer denotes the sum of max two non-overlapping subarrays
*/
int maxTwoSubArrays(vector<int> &nums)
{
// write your code here
vector<int> lRes(nums.size() , INT_MIN);
lRes[0] = nums[0];
int temp = nums[0];
for(int i=1 ; i < nums.size() ; i++)
{
temp = max(temp+nums[i] , nums[i]);
lRes[i] = max(temp , lRes[i-1]);
}
vector<int> rRes(nums.size() , INT_MIN);
rRes[nums.size()-1] = nums[nums.size()-1];
temp = nums[nums.size()-1];
for(int i=nums.size()-2 ; i >=0 ;i--)
{
temp = max(temp+nums[i] , nums[i]);
rRes[i] = max(temp , rRes[i-1]);
}
int res = INT_MIN;
for(int i=0 ; i+1 < nums.size() ; i++)
{
int t = lRes[i] + rRes[i+1];
res = res > t ? res : t;
}
return res;
}
};