题目描述
思路
思路参考leetcode官方题解:
要计算三个无重叠子数组的最大和,我们可以枚举第三个子数组的位置,同时维护前两个无重叠子数组的最大和及其位置。
要计算两个无重叠子数组的最大和,我们可以枚举第二个子数组的位置,同时维护第一个子数组的最大和及其位置。
因此,我们首先来解决单个子数组的最大和问题,然后解决两个无重叠子数组的最大和问题,最后解决三个无重叠子数组的最大和问题。
前言一:单个子数组的最大和
我们用滑动窗口来解决这一问题。
滑动窗口是数组/字符串问题中常用的抽象概念。窗口通常是指在数组/字符串中由开始和结束索引定义的一系列元素的集合,即闭区间 [i,j]
。而滑动窗口是指可以将两个边界向某一方向「滑动」的窗口。例如,我们将 [i,j]
向右滑动 1
个元素,它将变为 [i+1,j+1]
。
设 sum1
为大小为 k
的窗口的元素和,当窗口从[i−k+1,i]
向右滑动 1
个元素后,sum1
增加了nums[i+1]
,减少了nums[i-k+1]
。据此我们可以 O(1)
地计算出向右滑动 1
个元素后的窗口的元素和。
我们从[0,k−1]
开始,不断地向右滑动窗口,直至窗口右端点到达数组末尾时停止。统计这一过程中的sum1
的最大值(记作maxsum1
)及其对应位置。
前言二:两个无重叠子数组的最大和
我们使用两个大小为k
的滑动窗口。设sum1
为第一个滑动窗口的元素和,该滑动窗口从[0,k-1]
开始;sum2
为第二个滑动窗口的元素和,该滑动窗口从[k,2k-1]
开始。
我们同时向右滑动这两个窗口,并维护sum1
的最大值maxsum1
及其对应位置。每次滑动时,计算当前maxsum1
与sum2
之和。统计这一过程中的maxsum1+sum2
的最大值(记作maxsum12
)及其对应位置。
滑动窗口法
回到本题,我们使用三个大小为k
的滑动窗口。设sum1
为第一个滑动窗口的元素和,该滑动窗口从[0,k-1]
;sum2
为第二个滑动窗口的元素和,该滑动窗口从[k,2k-1]
;sum3
为第三个滑动窗口的元素和,该滑动窗口从[2k,3k-1]
开始。
我们同时向右滑动这三个窗口,按照前言二的方法并维护maxsum12
及其对应位置。每次滑动前,计算当时maxsum12
与sum3
之和。统计这一过程中的maxsum12+sum3
的最大值及其对应位置。
对于题目要求的最小字典序,由于我们是从左到右遍历的,并且当且仅当元素和超过最大元素和时才更新,从而保证求出来的下标列表时字典序最小的。
代码实现
Leetcode代码实现
class Solution {
public:
vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k)
{
int sum1=0,maxsum1=0,maxsum1Index=0;
int sum2=0,maxsum12=0,maxsum12Index1=0,maxsum12Index2=0;
int sum3=0,maxtotal