In a given array nums of positive integers, find three non-overlapping subarrays with maximum sum.

Each subarray will be of size k, and we want to maximize the sum of all 3*k entries.

Return the result as a list of indices representing the starting position of each interval (0-indexed). If there are multiple answers, return the lexicographically smallest one.

Example:

Input: [1,2,1,2,6,7,5,1], 2
Output: [0, 3, 5]
Explanation: Subarrays [1, 2], [2, 6], [7, 5] correspond to the starting indices [0, 3, 5].
We could have also taken [2, 1], but an answer of [1, 3, 5] would be lexicographically larger.

Note:

  • nums.length will be between 1 and 20000.
  • nums[i] will be between 1 and 65535.
  • k will be between 1 and floor(nums.length / 3).

这道题给了我们一个只包含正数的数组,让我们找三个长度为k的不重叠的子数组,使得所有子数组的数字之和最大。首先我们应该明确的是,暴力搜索在这道题上基本不太可能,因为遍历一个子数组的复杂度是平方级,遍历三个还不得六次方啊,看OJ不削你~那么我们只能另辟蹊径,对于这种求子数组和有关的题目时,一般都需要建立累加和数组,为啥呢,因为累加和数组可以快速的求出任意长度的子数组之和,当然也能快速的求出长度为k的子数组之和。因为这道题只让我们找出三个子数组,那么我们可以先确定中间那个子数组的位置,这样左右两边的子数组的位置范围就缩小了,中间子数组的起点不能是从开头到结尾整个区间,必须要在首尾各留出k个位置给其他两个数组。一旦中间子数组的起始位置确定了,那么其和就能通过累加和数组快速确定。那么现在就要在左右两边的区间内分别找出和最大的子数组,遍历所有的子数组显然不是很高效,如何快速求出呢,这里我们需要使用动态规划Dynamic Programming的思想来维护两个DP数组left和right,其中:

left[i]表示在区间[0, i]范围内长度为k且和最大的子数组的起始位置

right[i]表示在区间[i, n - 1]范围内长度为k且和最大的子数组的起始位置

这两个dp数组各需要一个for循环来更新,left数组都初始化为0,前k个数字没办法,肯定起点都是0,变量total初始化为前k个数字之和,然后从第k+1个数字开始,每次向前取k个,利用累加和数组sums快速算出数字之和,跟total比较,如果大于total的话,那么更新total和left数组当前位置值,否则的话left数组的当前值就赋值为前一位的值。同理对right数组的更新也类似,total初始化为最后k个数字之和,然后从前一个数字向前遍历,如果大于total,更新total和right数组的当前位置,否则right数组的当前值就赋值为后一位的值。一旦left数组和right数组都更新好了,那么就可以遍历中间子数组的起始位置了,然后我们可以通过left和right数组快速定位出左边和右边的最大子数组的起始位置,并快速计算出这三个子数组的所有数字之和,用来更新全局最大值mx,如果mx被更新了的话,记录此时的三个子数组的起始位置到结果res中,参见代码如下:

class Solution {
public:
vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
int n = nums.size(), mx = INT_MIN;
vector<int> sums{}, res, left(n, ), right(n, n - k);
for (int num : nums) sums.push_back(sums.back() + num);
for (int i = k, total = sums[k] - sums[]; i < n; ++i) {
if (sums[i + ] - sums[i + - k] > total) {
left[i] = i + - k;
total = sums[i + ] - sums[i + - k];
} else {
left[i] = left[i - ];
}
}
for (int i = n - - k, total = sums[n] - sums[n - k]; i >= ; --i) {
if (sums[i + k] - sums[i] >= total) {
right[i] = i;
total = sums[i + k] - sums[i];
} else {
right[i] = right[i + ];
}
}
for (int i = k; i <= n - * k; ++i) {
int l = left[i - ], r = right[i + k];
int total = (sums[i + k] - sums[i]) + (sums[l + k] - sums[l]) + (sums[r + k] - sums[r]);
if (mx < total) {
mx = total;
res = {l, i, r};
}
}
return res;
}
};

类似题目:

Best Time to Buy and Sell Stock III

参考资料:

https://leetcode.com/problems/maximum-sum-of-3-non-overlapping-subarrays/discuss/108231/C++Java-DP-with-explanation-O(n)

https://leetcode.com/problems/maximum-sum-of-3-non-overlapping-subarrays/discuss/108246/C++-O(n)-time-O(n)-space-concise-solution

https://leetcode.com/problems/maximum-sum-of-3-non-overlapping-subarrays/discuss/108230/Clean-Java-DP-O(n)-Solution.-Easy-extend-to-Sum-of-K-Non-Overlapping-SubArrays

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Maximum Sum of 3 Non-Overlapping Subarrays 三个非重叠子数组的最大和的更多相关文章

  1. [LeetCode] 689. Maximum Sum of 3 Non-Overlapping Subarrays 三个非重叠子数组的最大和

    In a given array nums of positive integers, find three non-overlapping subarrays with maximum sum. E ...

  2. [leetcode]689. Maximum Sum of 3 Non-Overlapping Subarrays三个非重叠子数组的最大和

    In a given array nums of positive integers, find three non-overlapping subarrays with maximum sum. E ...

  3. Java实现 LeetCode 689 三个无重叠子数组的最大和(换方向筛选)

    689. 三个无重叠子数组的最大和 给定数组 nums 由正整数组成,找到三个互不重叠的子数组的最大和. 每个子数组的长度为k,我们要使这3*k个项的和最大化. 返回每个区间起始索引的列表(索引从 0 ...

  4. [Swift]LeetCode689. 三个无重叠子数组的最大和 | Maximum Sum of 3 Non-Overlapping Subarrays

    In a given array nums of positive integers, find three non-overlapping subarrays with maximum sum. E ...

  5. [Swift]LeetCode1031. 两个非重叠子数组的最大和 | Maximum Sum of Two Non-Overlapping Subarrays

    Given an array A of non-negative integers, return the maximum sum of elements in two non-overlapping ...

  6. [LeetCode] 918. Maximum Sum Circular Subarray 环形子数组的最大和

    Given a circular array C of integers represented by A, find the maximum possible sum of a non-empty ...

  7. leetcode面试题42. 连续子数组的最大和

      总结一道leetcode上的高频题,反反复复遇到了好多次,特别适合作为一道动态规划入门题,本文将详细的从读题开始,介绍解题思路. 题目描述示例动态规划分析代码结果 题目   面试题42. 连续子数 ...

  8. [Swift]LeetCode918. 环形子数组的最大和 | Maximum Sum Circular Subarray

    Given a circular array C of integers represented by A, find the maximum possible sum of a non-empty ...

  9. 连续子数组的最大和/1007. Maximum Subsequence Sum (25)

    题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果向量 ...

随机推荐

  1. 涉及模式之 装饰器模式详解(与IO不解的情缘)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. LZ到目前已经写了九个设计模 ...

  2. 四则运算题目生成(python版)

    四则运算题目生成-基于控制台 项目托管在码云:飞机票 需求分析 根据控制台提示信息,输入题目生成相关配置参数 题目生成数量 数字范围 式子中是否有分数 .... 程序支持 10000 题目生成 题目与 ...

  3. 四则运算程序(java基于控制台)

    四则运算题目生成程序(基于控制台) 一.题目描述: 1. 使用 -n 参数控制生成题目的个数,例如 Myapp.exe -n 10 -o Exercise.txt 将生成10个题目. 2. 使用 -r ...

  4. 2017-2018-1 20155215 第九周 加分项 PWD命令的实现

    1 学习pwd命令 Linux中用 pwd 命令来查看"当前工作目录"的完整路径. 简单得说,每当你在终端进行操作时,你都会有一个当前工作目录. 在不太确定当前位置时,就会使用pw ...

  5. 201621123062《java程序设计》第九周作业总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 思维导图1:(对集合部分做了一些改动和细化) 思维导图2:(泛型) 1.2 选做:收集你认为有用的代码片段 代 ...

  6. iOS 播放音频的几种方法

    Phone OS 主要提供以下了几种播放音频的方法: System Sound Services AVAudioPlayer 类 Audio Queue Services OpenAL 1. Syst ...

  7. [USACO4.1]麦香牛块Beef McNuggets

    https://www.luogu.org/problemnew/show/P2737 给出n个数ai,求这n个数不能累加出的最大的数 最大的数无限大或能凑出所有的自然数则输出0 n<=10,a ...

  8. 【技巧】Java工程中的Debug信息分级输出接口及部署模式

    也许本文的标题你们没咋看懂.但是,本文将带大家领略输出调试的威力. 灵感来源 说到灵感,其实是源于笔者在修复服务器的ssh故障时的一个发现. 这个学期初,同袍(容我来一波广告产品页面,同袍官网)原服务 ...

  9. Mac使用brew安装软件

    Homebrew官方网站:https://brew.sh/1,安装brew,Mac中打开Termal输入命令: /usr/bin/ruby -e "$(curl -fsSL https:// ...

  10. Mego(03) - ORM框架的新选择

    前言 从之前的两遍文章可以看出ORM的现状. Mego(01) - NET中主流ORM框架性能对比 Mego(02) - NET主流ORM框架分析 首先我们先谈下一个我们希望的ORM框架是什么样子的: ...