#面试题#前伸后缩法

来源:互联网 发布:仿中华养生网源码 编辑:程序博客网 时间:2024/06/06 03:19


题目:给定长度为n的整数数列:a0,a1,..,an-1,以及整数S。这个数列会有连续的子序列的整数总和大于S的,求这些数列中,最小的长度。

 

如果数列中有正有负,则直接用 O(n^2)的算法。

 

现在讨论 数列中全为非负数的情况:

令i, j 都指向 数列的第一个元素,之后循环执行以下步骤:

1. j++ 直到 a[i] + .... + a[j] > S;

2. i++ 直到 a[i] + ..... + a[j] <= S, 同时更新最小长度。(这里注意i <= j)

 

之所以可以这么做的理论证明是:

1.如果 a[i] + .... + a[j] > S, 那么显然不用再枚举 a[i] + .... + a[j+1] 的情况,也同样不用枚举a[i-1] + ..... + a[j] 的情况。而只需要枚举a[i+1] + ...... + a[j]的情况(因此可以“后缩”)。

2.如果 a[i] + .... + a[j] <= S, 那么 a[i+1] + .... + a[j] 显然也是 <= S的,不满足情况,所以也无需枚举。(因此需要“前伸”)。

 

代码如下: