尺取法

给定长度为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);
	}

}

尺取法

但我们还可以更加高效的求解这个问题,我们设以 a_{s} 开始,总和最初大于s时的连续子序列为 a_{s}+...+a_{t-1} ,   这时

                                                a_{s+1}+.....+a_{t-2}<a_{s}+......+a_{t-2}<s

所以从a_{s+1}开始总和最初超过s的连续子序列如果是

                                                a_{s+1}+.....+a_{t'+1}

则必然有t<=t',利用这一性质,便可以设计出如下算法;

(1):以s=t=sum=0初始化.

(2):只要依然有sum<s,就不断将sum加a_{t},并将 t 加1.

(3):如果(2)中无法满足sum>=s则终止,否则的话,更新 res=min(res,t-s).

(4):将sum减去a_{s},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);

	}

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值