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. 连续子数 ...
随机推荐
- 制作 Python Docker 镜像的最佳实践
概述 ️Reference: 制作容器镜像的最佳实践 这篇文章是关于制作 Python Docker 容器镜像的最佳实践.(2022 年 12 月更新) 最佳实践的目的一方面是为了减小镜像体积,提升 ...
- PTA散列表平方探测法解决冲突
PTA散列表平方探测法解决冲突 核心问题 当所有的位置都被填上了,且不能插入关键词,要进入死循环了怎么办? 题目 本题的任务很简单:将给定的无重复正整数序列插入一个散列表,输出每个输入的数字在 ...
- DID 2022-12-02
DID第二节课 最低工资对就业率影响(DID) 宾夕法尼亚VS新泽西的快餐店,用边界的好处:在用最低工资法之前,两地工资情况差不多,DID需要两期,92年11月实施,之前之后做电话访问. 数据越全的估 ...
- 封装 avm 组件经验分享
avm.js 是一个跨端开发框架,AVM(Application-View-Model)前端组件化开发模式基于标准Web Components组件化思想,提供包含虚拟DOM和Runtime的编程框架a ...
- java线程基础知识整理
目录 线程基本概念 1.java实现线程 2.线程的生命周期 3.线程常用的方法 3.1.sleep() 3.2.interrupt方法 3.3.stop方法 4.线程调度 4.1.常见的线程调度模型 ...
- MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(1)-后端项目框架搭建
前言: 前面的四个章节我们主要讲解了MongoDB的相关基础知识,接下来我们就开始进入使用.NET7操作MongoDB开发一个ToDoList系统实战教程. MongoDB从入门到实战的相关教程 Mo ...
- [OpenCV实战]46 在OpenCV下应用图像强度变换实现图像对比度均衡
本文主要介绍基于图像强度变换算法来实现图像对比度均衡.通过图像对比度均衡能够抑制图像中的无效信息,使图像转换为更符合计算机或人处理分析的形式,以提高图像的视觉价值和使用价值.本文主要通过OpenCV ...
- Cesium for Unreal加载倾斜摄影
本文介绍UE4中通过Cesium插架加载本地倾斜摄影模型.Cesium for Unreal插件运行在UE环境何总运行Cesium,这样方便做一个GIS应用. 安装Cesium for Unreal插 ...
- Spring 和 Spring MVC的区别
Spring 和 Spring MVC的区别 学习Spring MVC也有几天时间了,那么Spring和Spring MVC的区别到底在哪里,二者是什么关系呢?认为二者是一个东西那肯定是不对的,而 ...
- P1005 [NOIP2007 提高组] 矩阵取数游戏
题目传送门 前言 今天依旧是不写高精的一天呢!(是的,这位作者又只拿了开 \(LL\) 的 \(\color{yellow}{60}\) 分) 思路描述 看到数据 \(n,m \le 80(30)\) ...