最短区间(尺取法)

  • 现在给定一个整数s以及一个长度为n的整数数列a0,a1,a2,a3…an−1 (全为正数),
    请你求出总和不小于s的连续子序列的长度的最小值。如果解不存在,则输出0。

Input
第一行:两个整数,表示 s 与 n,其中1≤s≤10^9,1≤n≤500000; 第二行:n个用空格隔开的整数,表示 a0 a1 … an−1,其中对于任意ai有1≤ai≤10^9。

Output
输出总和不小于s的连续子序列的长度的最小值。 如果解不存在,则输出0。

Sample Input
50 20
10 8 9 3 11 8 5 1 1 1 1 20 8 9 11 4 13 22 9 6

Sample Output
4

分析:
根据题意是要找出一段连续的序列,使该段序列各个元素的和大于等于s,且该序列的长度最小。第一反应是暴力模拟,从第一个元素开始,将该元素及之后长度依次增加地计算总和,如果和大于等于s,而且如果长度比之前小的话,就将此时的长度保存为最小,依次循环,直到最后一个元素。
但是由于数据量过大,这种方法虽然直观,但是很耗时间。所以选取一个更高效的算法——尺取法。
尺取法: 就是设置两个变量,就比如设置a和b,刚开始都指向0位置,然后a不动,b继续向下指,每指一次就求一次和,直到b不能继续向下指或和大于等于s。

  1. 当b没有指向最后一个元素而且和大于等于s时,再用现在a和b之间的长度与之前的长度比较取最小值。再从当前数字的和中减去a所指的数字,a再向下指一位,b继续向下指。继续重复上述过程 。
  2. 当b指向最后一个元素而且此时和没有大于s,那么就跳出循环,因为已经不可能再找到大于等于s的序列范围了。

如下所示一个例子:在6个数字中,找出最小的比10大的序列。
在这里插入图片描述
尺取法可以将不必要的相加和比较有效的筛除,效率大大提高。
以下给出代码:(自己动手打一遍更好理解┗|`O′|┛ )
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值