给定长度为n的数列正整数 a1,a2,a3,a4,.....an-1,以及整数s,求出总和不小于s的连续子序列的长度最小值,如果不存在,输出0.
可以通过前缀和的方式来做,
代码如下:
package Test2;
import java.util.Arrays;
import java.util.Scanner;
public class L5 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int s = sc.nextInt();
int[] a = new int[n + 1];
int[] sum = new int[n + 1];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
sum[0] = a[0];
for (int i = 1; i < n; i++) {
sum[i] = sum[i - 1] + a[i];
}
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(sum));
if (s > sum[n - 1]) {
System.out.println(0);
return;
}
int min = 10000;
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
if (min > sum[j] - sum[i] && sum[j] - sum[i] >= s)
min = j - i;
}
}
if (min == 10000) {
System.out.println(0);
return;
}
System.out.println(min);
}
}
尺取法
但我们还可以更加高效的求解这个问题,我们设以 开始,总和最初大于s时的连续子序列为 , 这时
所以从开始总和最初超过s的连续子序列如果是
则必然有,利用这一性质,便可以设计出如下算法;
(1):以s=t=sum=0初始化.
(2):只要依然有sum<s,就不断将sum加,并将 t 加1.
(3):如果(2)中无法满足sum>=s则终止,否则的话,更新 res=min(res,t-s).
(4):将sum减去,s增加1然后回到(2).
代码如下:
package Test2;
import java.util.Scanner;
public class L6 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int S = sc.nextInt();
int[] a = new int[n + 1];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
int res = n + 1;
int s = 0, t = 0, sum = 0;
while(true) {
while (t < n && sum < S)
sum += a[t++];
if (sum < S)
break;
res = Math.min(res, t - s);
sum -= a[s++];
}
if (res > n)
res = 0;
System.out.println(res);
}
}