文章目录

  • 本题分析
  • 题目链接

本题分析

题目重述: 给定一个非负的数组,要求将其分成3个非空的三段,要求每一段的数字之和依次递增(可以相等),求总共有几种分法。

题目解答:

双指针算法

思路:枚举第二个分界点,看第一个分界点有多少种选择 。

数组下标从1开始,即从1到n: a[1] ,a[2],…a[n], 第二个分界点下标是i,第一个分界点下标是x,这里下标属于后一段。这样把数组分成三段(用下标来表示):[1~x-1], [x ~i-1],[ i ~ n]. 三段之和分别记为A,B,C

对于分界点i,我们看第一个分界点x的取值范围,假设其可取的最小下标为j,可取的最大下标为k,那么对于第二个分界点i,满足题意的方案数就有:k-j+1 种。

比如样例,

输入:nums = [1,2,2,2,5,0]
输出:3
解释:nums 总共有 3 种好的分割方案:
[1] [2] [2,2,5,0]
[1] [2,2] [2,5,0]
[1,2] [2,2] [5,0]
下标从1开始 1 2 3 4 5 6
数组内容 1 2 2 2 5 0

假设第二个分界点下标i=4,则C=7,第一个分界点x可取多少呢? (j,k)=(3,3),故此时的方案数: 3-3+1=1种。

假设第二个分界点 i=5,则C=5,那么第一个分界点x可取多少呢? (j,k)=(3,4),故此时的方案数: 4-3+1=2种。

总的方案数就是1+2=3种。

下面的问题就是这个 j和k 怎么求?

j的含义是:i给定之后, 第一个分界点最靠前可以取到什么位置。

i需要满足什么呢?

j越往左走,那么中间B就会越大,为了满足B≤C,那么必然j有下界。

在第二个分界点往后走的时候,C在变小,为了满足B≤C,j也应该往后走。也就是说,j会随着i向右移而单调向右移

k的含义是:i给定之后,第二个分界点最靠后可以取到什么位置。

k需要满足什么呢?

k需要满足a[k]~a[i-1]的和≥ a[1] ~a[k-1]的和,即B≥A。

k往右走,在i固定时,B会变小,A会变大,为了满足B≥A,必然存在一个最大的k,越过了这个边界,就不再满足B≥A。

根据上面 j的推理,可以利用反证法证明, k会随着i向右移而单调向右移

总之:最小取值j由右边(C≥B)限制, 最大取值 k由左边(A≤B)限制。

当然还有小技巧:可以使用前缀和来求出一段的和:通过O(1)的时间求出一段的和。

注意:下面对代码进行解释

对于边界(j,k)的判断思路不太一样

 while(s[n]-s[i-1] < s[i-1]-s[j-1]) j++;
while(  k+1<i  && s[k] <= s[i-1]-s[k])  k++;

下面进行解释:

对于 左边界j:左边界被右边限制,只要B大于C,j就一直j++,直到第一个满足B小于等于C。这就是满足题意的第一个分界点的最小取值,即左边界。

对于右边界k:右边界k被左边限制,我们要试探性地往右走:对于下标是k+1的第一个分界点,是否满足 A小于等于B,如果满足,就继续k++。当然,第一个下标永远小于第二个下标i,尝试k+1时也要满足k+1<i.

ac代码

class Solution {public:int waysToSplit(vector<int>& nums) {int n  = nums.size(),mod = 1e9 +7;vector<int> s(n+1); //前缀和数组for(int i=1;i<=n;i++)  s[i] =s[i-1]+nums[i-1]; //下标往后移动了一个,从1开始int res=0;//枚举第二个分界点i,记住下标从1开始for( int i=3, j=2, k=2; i<= n; i++){//判断(j,k)的位置//对于左边界j:如果B>C,j一直往右移动,直到B≤Cwhile(s[n]-s[i-1] < s[i-1]-s[j-1]) j++;//对于右边界k: 如果A一直小于等于B,k就一直往右移//本身是A小于等于B 即[1,k-1] ≤ [k,i-1]//试探一下,看k取k+1是否成立,如果成立就k++。//现在要试探k+1   即 [1,k] ≤ [k+1, i-1]while(  k+1<i  && s[k] <= s[i-1]-s[k])  k++;if(j<=k && s[k-1] <= s[i-1]-s[k-1] &&  s[n]-s[i-1] >= s[i-1]-s[j-1] )res=( res+ k-j+1) %mod;}return res;}
};

题目链接

Leetcode1712. 将数组分成三个子数组的方案数

Leetcode1712. 将数组分成三个子数组的方案数[C++题解]:双指针和前缀和相关推荐

  1. LeetCode 1712. 将数组分成三个子数组的方案数(前缀和 + 二分查找)

    文章目录 1. 题目 2. 解题 221 / 3117,前7.1% 574 / 9692,前 5.9% 周赛前2题如下: LeetCode 5641. 卡车上的最大单元数(排序,模拟) LeetCod ...

  2. 【动态规划】将一个包含m个整数的数组分成n个数组,每个数组的和尽量接近,及其变形(Python实现)

    背景 实际的问题来源于LQA系统的人员分配工作量,有两种方式,一种是 平均分配,一种是按给定比例分配.不需要AC,能得到符合题意的解就算达成目标. 平均分配 一个order订单包含一个xls表格,内含 ...

  3. LeetCode 2035. 将数组分成两个数组并最小化数组和的差

    文章目录 一.题目 1.题目描述 2.基础框架 3.原题链接 二.解题报告 1.思路分析 2.算法详解 3.时间复杂度 4.代码详解 三.本题小知识 四.加群须知 一.题目 1.题目描述   给你一个 ...

  4. 网易实习生算法组编程题二:求数组的两个子数组和的最大值

    求一个正整数数组的两个子数组,使其和相等,找出满足这样要求的子数组和的最大值,若不存在,则返回-1.比如[1,1,2,3,5,20],结果为6. #include<iostream> #i ...

  5. LeetCode 2035. 将数组分成两个数组并最小化数组和的差(状态压缩DP)

    文章目录 1. 题目 2. 解题 1. 题目 给你一个长度为 2 * n 的整数数组. 你需要将 nums 分成 两个 长度为 n 的数组,分别求出两个数组的和,并 最小化 两个数组和之 差的绝对值 ...

  6. 一个子数组最大值的问题

    题目要求: 1.输入一个整形数组,数组里有正数也有负数. 2.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 3.求所有子数组的和的最大值.要求时间复杂度为O(n)      发表一 ...

  7. php 把一个数组分成有n个元素的二维数组的算法

    一.第一种解法 <?php //把一个数组分成几个数组//$arr 是数组//$num 是数组的个数function partition($arr,$num){//数组的个数$listcount ...

  8. 寻找数组中只出现一次的数

    题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). 分析:首先考虑这个问题的一个简单版本:一个数组里除了 ...

  9. 结对开发--求二维数组的最大子数组

    小组成员:信1201-1班  黄亚萍 信1201-1班  袁亚姣 一.题目要求 程序要使用的数组放在一个叫 input.txt 的文件中,  文件格式是: 数组的行数, 数组的列数, 每一行的元素,  ...

最新文章

  1. LeNet5,AlexNet,MobileNet它们的前身你知道吗?
  2. Kali渗透测试——UPNP网关发现工具Miranda
  3. origin画图_把heatmap翻一转:imshow的origin和extent
  4. 大剑无锋之你了解HTTPS吗?那么它为什么安全?【面试推荐】
  5. 英语笔记:写作:Free admissionsto museums
  6. python logger_牛逼!python中的logging模块居然这么好用!
  7. 网络拓扑结构与静态特征
  8. 把RDD简单的转换成DataFrames
  9. 一块神奇的树莓派电子板竟让我学会了Linux系统
  10. angular遇到问题
  11. 关于代理服务器的原理及用法
  12. 【原创】STM32低功耗模式及中断唤醒(基于BMI160及RTC)的研究
  13. 用纯fme批量生成界址点成果表(模板格式全部自拟)
  14. AWT:实现简单的java计算器
  15. 左神算法学习日记——二叉树遍历(二)
  16. 并发控制五(封锁的粒度)
  17. linux运行docker容器,添加映射端口
  18. 已解决requests.exceptions.ConnectTimeout: HTTPConnectionPool(host=‘123.96.1.95‘, port=30090): Max retri
  19. 《The C Programming Language》答案(第一章)
  20. 案例-站狼云品智美站助力必信空调中国制造领先品牌

热门文章

  1. 如何用CMD开启3389与查看3389端口
  2. 即时通讯 TCP UDP
  3. JavaScript要点 (二) 使用误区
  4. Reveal:分析iOS UI该武器
  5. 【Android Developers Training】 104. 接受地点更新
  6. 2013年3月空调类品牌网络知名度排名
  7. 如何捕获window.print点击打印或取消_原来1:1的CAD图纸要这样打印!学了这么久才知道...
  8. 在形态的世界里寻找基数的影子
  9. 谷歌身份验证器验证码不对怎么回事_地面最强下载器:IDM+【安卓】详细介绍...
  10. java各种包的用途