例题:给定长度为n的数列整数a0,a1,a2,an-1,以及整数s,求出总和不小于s的连续子序列的长度的最小值,如果不存在输出0.
尺取法的思路:
(1)以s=t=sum=0初始化。
(2)只要有sum<s,就不断将sum增加at,并将t增加1.
(3)如果(2)中的要求无法满足sum>=s则终止,否则的话更新res=min(res,t-s)
(4)将sum减去as,s增加1然后回到(2)。
对于这个算法,因为最多变化n次,因此只需要0(n)的复杂度就可以解决这个问题。
void solve() {
int res = n + 1;
int s = 0, t = 0, sum = 0;
for (;;) {
while (t < n && sum < s) {
sum += a[t++];
}
if (sum < s) break;
res = min(res, t - s);
sum -= a[s++];
}
if (res < n) {
res = 0;
}
cout << res << endl;
}
数据一:n=10,s=15,a={5.1.3.5.10.7.4.9.2.8}
数据一对应的的区间变化。
5 | 1 | 3 | 5 | 10 | 7 | 4 | 9 | 2 | 8 |
5 | 1 | 3 | 5 | 10 | 7 | 4 | 9 | 2 | 8 |
5 | 1 | 3 | 5 | 10 | 7 | 4 | 9 | 2 | 8 |
5 | 1 | 3 | 5 | 10 | 7 | 4 | 9 | 2 | 8 |
5 | 1 | 3 | 5 | 10 | 7 | 4 | 9 | 2 | 8 |
5 | 1 | 3 | 5 | 10 | 7 | 4 | 9 | 2 | 8 |
5 | 1 | 3 | 5 | 10 | 7 | 4 | 9 | 2 | 8 |
5 | 1 | 3 | 5 | 10 | 7 | 4 | 9 | 2 | 8 |