[LeetCode] Maximum Sum of 3 Non-Overlapping Subarrays 三个非重叠子数组的最大和
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.lengthwill be between 1 and 20000.nums[i]will be between 1 and 65535.kwill 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
参考资料:
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Maximum Sum of 3 Non-Overlapping Subarrays 三个非重叠子数组的最大和的更多相关文章
- [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 ...
- [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 ...
- Java实现 LeetCode 689 三个无重叠子数组的最大和(换方向筛选)
689. 三个无重叠子数组的最大和 给定数组 nums 由正整数组成,找到三个互不重叠的子数组的最大和. 每个子数组的长度为k,我们要使这3*k个项的和最大化. 返回每个区间起始索引的列表(索引从 0 ...
- [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 ...
- [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 ...
- [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 ...
- leetcode面试题42. 连续子数组的最大和
总结一道leetcode上的高频题,反反复复遇到了好多次,特别适合作为一道动态规划入门题,本文将详细的从读题开始,介绍解题思路. 题目描述示例动态规划分析代码结果 题目 面试题42. 连续子数 ...
- [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 ...
- 连续子数组的最大和/1007. Maximum Subsequence Sum (25)
题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果向量 ...
随机推荐
- oracle中事务处理--事务隔离级别
概念:隔离级别定义了事务与事务之间的隔离程度. ANSI/ISO SQL92标准定义了一些数据库操作的隔离级别(这是国际标准化组织定义的一个标准而以,不同的数据库在实现时有所不同). 隔离级别 脏读 ...
- DevOps实践之Gitlab安装部署
All GitLab packages are posted to our package server and can be downloaded. We maintain five repos: ...
- 指令-arContentedit-可编辑的高度自适应的div
<div ar-contentedit="true" contenteditable="true" contenteditable="pla ...
- 记录python接口自动化测试--从excel中读取params参数传入requests请求不生效问题的解决过程(第七目)
在第六目把主函数写好了,先来运行一下主函数 从截图中可以看到,请求参数打印出来了,和excel中填写的一致 但是每个接口的返回值却都是400,提示参数没有传进去,开始不知道是什么原因(因为excel中 ...
- iOS中CocoaPods的安装及错误详解
什么是CocoaPods CocoaPods是OS X和iOS下的一个第三类库管理工具,通过CocoaPods工具我们可以为项目添加被称为"Pods"的依赖库(这些类库必须是Coc ...
- git中级技能
中级技能(上) 一.实验说明 从本节开始,我们会介绍一些中级和高级的用法,这些用法很少用到,前面三节的内容已经满足了日常工作需要,从本节开始的内容可以简单了解,需要的时候再 ...
- maven创建web工程
使用eclipse插件创建一个web project 首先创建一个Maven的Project如下图 我们勾选上Create a simple project (不使用骨架) 这里的Packing 选择 ...
- zookeeper入门系列:paxos协议
上一章讨论了一种强一致性的情况,即需要分布式事务来解决,本章我们来讨论一种最终一致的算法,paxos算法. paxos算法是由大牛lamport发明的,关于paxos算法有很多趣事.比如lamport ...
- python之路--day15---软件开发目录规范
软件开发目录规范 bin--启动文件 conf--配置文件 core--核心代码 db--数据文件 lib--常用功能代码 log--日志文件 readme--软件介绍
- JAVA_SE基础——36.static的实际应用
什么时候定义静态函数 如果功能内部没有访问到非静态数据(对象的特有数据.那么该功能就可以定义为静态) P.S. 静态方法作为类和接口的重要组成部分,可以通过类名或接口直接访问,通常将那些使用频率较高的 ...