[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偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果向量 ...
随机推荐
- android:layout_weight属性详解
1. 按比例显示LinearLayout内各个子控件,需设置android:layout_width="0dp",如果为竖直方向的设置android:layout_height=& ...
- synchronized 原理分析
synchronized 原理分析 1. synchronized 介绍 在并发程序中,这个关键字可能是出现频率最高的一个字段,他可以避免多线程中的安全问题,对代码进行同步.同步的方式其实就是隐 ...
- (译文)开始学习Vue——构建你的第一个Vue应用
我们要构建如下组件:(最终代码在这里:https://codesandbox.io/s/38k1y8x375) 开始 Vue是支持单文件组件的,但是我们不准备这么做.你也可以构建一个全局的组件,通过V ...
- Software Engineering-HW2
title: Software Engineering-HW2 date: 2017-09-21 10:35:47 tags: HW --- 题目描述 从<构建之法>第一章的 " ...
- 关于Mac OS 使用GIT的引导
1. 下载Git installer 链接地址:https://ncu.dl.sourceforge.net/project/git-osx-installer/git-2.14.1-intel-un ...
- C语言——第0次作业(二)
1.翻阅邹欣老师的关于师生关系博客,并回答下列问题,每个问题的答案不少于500字: 1.最理想的师生关系是健身教练和学员的关系,在这种师生关系中你期望获得来自老师的哪些帮助? 在现代软件工程讲义 0 ...
- django搭建web (四) models.py
demo 该demo模型主要是用于问题,选择单个或多个答案的问卷形式应用 # -*- coding: utf-8 -*- from __future__ import unicode_literals ...
- Flask 学习 十四 测试
获取代码覆盖报告 安装代码覆盖工具 pip install coverage manage.py 覆盖检测 COV = None if os.environ.get('FLASK_COVERAGE') ...
- The method getTextContent() is undefined for the type Node
eclipse 中 如果加入了 其他了xfire 等其他xml解析包的话,使用org.w3c.dom.Node下的getTextContent()方法会出现The method getTextCont ...
- JAVA_SE基础——52.匿名内部类
电信的电箱烧了,害我断了2天网,真拿命,耽误了 Java匿名内部类的总结: 没有名字的内部类.就是内部类的简化形式.一般只用一次就可以用这种形式.匿名内部类其实就是一个匿名子类对象.想要定义匿名内部类 ...