1031. 两个非重叠子数组的最大和
关键词:前缀和
题目来源:1031. 两个非重叠子数组的最大和 – 力扣(Leetcode)
题目描述
T前缀和
给你一个整数数组 nums
和两个整数 firstLen
和 secondLen
,请你找出并返回两个非重叠 子数组 中元素的最大和,长度分别为 firstLen
和 secondLen
。
长度为 firstLen
的子数组可以出现在长为 secondLen
的子数组之前或之后,但二者必须是不重叠的。
子数组是数组的一个 连续 部分。
输入:nums = [0,6,5,2,2,5,1,9,4], firstLen = 1, secondLen = 2
输出:20
解释:子数组的一种选择中,[9] 长度为 1,[6,5] 长度为 2。
输入:nums = [3,8,1,3,2,1,8,9,0], firstLen = 3, secondLen = 2
输出:29
解释:子数组的一种选择中,[3,8,1] 长度为 3,[8,9] 长度为 2。
输入:nums = [2,1,5,6,0,9,5,0,3,8], firstLen = 4, secondLen = 3
输出:31
解释:子数组的一种选择中,[5,6,0,9] 长度为 4,[0,3,8] 长度为 3。
数据范围
1
问题分析
两个不重叠子数组必定位于某条分界线的两侧,于是,不妨枚举每条分界线,设其左侧子数组的最大值为l,右侧子数组的最大值为r,则,max{ l+r }即为答案。
如何快速知道分界线左/右侧的最大值呢?不妨先考虑长度为 firstLen
的子数组可以出现在长为 secondLen
的子数组之前的情况。由于子数组长度已知,且子数组连续,于是可采用一遍扫描,窗口不断向右/左滑动,预处理出所有分界线左/右侧的子数组的最大值。
当长度为 firstLen
的子数组在之后时,求解过程完全相同,于是,不妨上述求解过程封装成一个函数,将前后数组的长度作为参数。
为了方便计算指定区间元素和,可先预处理出前缀和。
时间复杂度:O(n)
空间复杂度:O(n)
代码实现
int maxSumTwoNoOverlap_2(vector &nums, int firstLen, int secondLen) {
// pre[i]表示[1..i]中指定长度的子数组的最大值
int n = nums.size(), pre[n+1];
// 前缀和
for (int i = 1; i = s; i--) {
curMax = max(nums[i + t - 1] - nums[i - 1], curMax);
res = max(pre[i] + curMax, res);
}
return res;
};
return max(f(firstLen, secondLen), f(secondLen, firstLen));
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net