LeetCode-689 三个无重叠子数组的最大和
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-sum-of-3-non-overlapping-subarrays
题目描述
给你一个整数数组 nums 和一个整数 k ,找出三个长度为 k 、互不重叠、且 3 * k 项的和最大的子数组,并返回这三个子数组。
以下标的数组形式返回结果,数组中的每一项分别指示每个子数组的起始位置(下标从 0 开始)。如果有多个结果,返回字典序最小的一个。
示例 1:
输入:nums = [1,2,1,2,6,7,5,1], k = 2
输出:[0,3,5]
解释:子数组 [1, 2], [2, 6], [7, 5] 对应的起始下标为 [0, 3, 5]。
也可以取 [2, 1], 但是结果 [1, 3, 5] 在字典序上更大。
示例 2:
输入:nums = [1,2,1,2,1,2,1,2,1], k = 2
输出:[0,2,4]
提示:
1 <= nums.length <= 2 * 104
1 <= nums[i] < 216
1 <= k <= floor(nums.length / 3)
解题思路
相信不少同学和我一样,看到题的第一反应就是这道题要用滑动窗口的方法来解。
最初的想法是使用贪心算法的思路,循环三次,每次找到没有被提取出来的子串中最大的那一个,但是做的过程中发现这样会破坏数组的顺序规律。比如nums = 1 6 8 7 7 1 8 1 k = 2的输入下,根据题意最终找出来的子串应该是,68 77 18,但是在贪心算法的思路下,就变成了87 18 16,出现这种情况的原因是用这种思路来找子串,仅仅考虑到了值最大这一条件,忽略了数字间的顺序关系。
于是产生了想法2.0,三个滑动窗口,同时进行滑动,分别记录每个窗口的和,如果三个窗口的和都是最大,那么总和一定是最大的,而由于三个窗口依次排列,所以理论上找出的子串应该都是可以保持顺序关系的,但是这种想法和第一种方法一样,找到最大值后会导致窗口停下,还是只考虑到局部最大,并没有考虑整体最大,并且,还可能三个窗口产生重叠。在更新一个窗口的时候,必须维护其他窗口,必须保证前窗口的尾部在后窗口的头部之前。
想法3.0就产生了,放弃局部的思想,将三个窗口间的关系利用总和来表示出了。首先将三个窗口分别设置为[0, k-1], [k, 2k-1], [2k, 3k-1],计算三个窗口分别的和,然后移动第一个窗口,如果移动后窗口的和大于原来的和,那么移动第一个窗口并且更新最大值。在假设第一个窗口基础上求第一个窗口和第二个窗口总和的最大值,这是非常关键的一步,如果仅仅求各自的最大值,就相当于人为割断了窗口间的联系,从而无法达到整体最大。如果第一和第二的总和大于之前的最大值,那么更新最大值,并且记录下这个时候窗口的位置。第三步同样也是在第一第二个窗口移动完的基础之上进行计算的,并且比较三个窗口的最大值与移动前最大值。如果大于移动前的最大值,那么记录移动后的窗口信息。
并且由于滑动窗口是三个窗口同步向前的,并没有停止的操作,所以保证了三个窗口不会发生重叠。
源码展示
class Solution {
public:
vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
vector<int> iRet;
int iSum[3] = { 0 }, iMax[3] = { 0 }, iIndex = 0, iIndex1 = 0, iIndex2 = k;
iRet.resize(3);
for(int i = 2 * k; i < nums.size(); i++)
{
iSum[0] += nums[i - 2 * k];
iSum[1] += nums[i - k];
iSum[2] += nums[i];
if(i >= 3 * k - 1)
{
if(iSum[0] > iMax[0])
{
iMax[0] = iSum[0];
iIndex = i - 3 * k + 1;
}
if(iSum[1] + iMax[0] > iMax[1])
{
iMax[1] = iSum[1] + iMax[0];
iIndex1 = iIndex;
iIndex2 = i - 2 * k + 1;
}
if(iSum[2] + iMax[1] > iMax[2])
{
iMax[2] = iMax[1] + iSum[2];
iRet = {iIndex1, iIndex2, i - k + 1};
}
iSum[0] -= nums[i - 3 * k + 1];
iSum[1] -= nums[i - 2 * k + 1];
iSum[2] -= nums[i - k + 1];
} }
return iRet;
}
};
运行结果
LeetCode-689 三个无重叠子数组的最大和的更多相关文章
- 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 ...
- [LeetCode] 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 ...
- [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 ...
- [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 ...
- 剑指offer三十之连续子数组的最大和
一.题目 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果向量 ...
- [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 ...
- 剑指Offer(三十):连续子数组的最大和
.# 剑指Offer(三十):连续子数组的最大和 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net ...
- leetcode面试题42. 连续子数组的最大和
总结一道leetcode上的高频题,反反复复遇到了好多次,特别适合作为一道动态规划入门题,本文将详细的从读题开始,介绍解题思路. 题目描述示例动态规划分析代码结果 题目 面试题42. 连续子数 ...
随机推荐
- React DevUI 18.0 正式发布🎉
Jay 是一位经验丰富并且对质量要求很高的开发者,对 Angular.React 等多种框架都很熟悉,我们在开源社区认识,在我做开源社区运营的过程中,Jay 给了我很多帮助,他也是 React Dev ...
- 【JVM】经典垃圾回收器
本文已收录至Github,推荐阅读 Java随想录 微信公众号:Java随想录 CSDN: 码农BookSea 转载请在文首注明出处,如发现恶意抄袭/搬运,会动用法律武器维护自己的权益.让我们一起维护 ...
- c++随笔测试(Corner of cpp)
在c++17下,程序的输出是什么?(有可能编译出错,有可能输出未知,有可能是未定义行为) 点击查看代码 #include<iostream> void foo(unsigned int) ...
- Junti单元测试
Junit单元测试 ## 测试分类 黑盒测试,白盒测试 黑盒测试,不需要写代码,给输入值,看程序是否能够输出期望的值 白盒测试,需要写代码的,关注程序的具体执行流程 Junit使用 是白盒测试 ### ...
- 【转载】VFP编写DLL,并调用
1. 编制DLL文件 ,保存为Temp.prg Define Class vfptools As Session OlePublic Procedure Add As Integer Lp ...
- 随身WIFI刷机记录 UF1003
设备说明 拿到手的设备是UF1003的设备,入手价格23元. https://www.bilibili.com/video/BV1Ne4y1n7su/ 视频会同步到BIlibili,感谢大家的支持,点 ...
- UOJ33 [UR#2] 树上 GCD
UOJ33 [UR#2] 树上 GCD 简要题意: 给定一棵有根树,对于每个 \(i \in [1,n)\),求出下式的值: \[Ans[i] = \sum_{u<v} \gcd({\rm{di ...
- Mybatis用List接收返回值
Mybatis 用 List 接收返回值 以 List<Map<String, Object>> 为例 1.XML内 resultType 为单条记录对应类型,设置成 java ...
- Java集合 - ConcurrentHashMap
介绍 ConcurrentHashMap 技术是为了解决问题而生的,ConcurrentHashMap 解决了多个线程同时操作一个 HashMap 时,可能出现的内部问题.当多个线程同时操作一个 Ha ...
- 学习ASP.NET Core Blazor编程系列二十一——数据刷新
学习ASP.NET Core Blazor编程系列文章之目录 学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应 ...