输出所有和为S的连续正数序列。
序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序(小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列?Good Luck!)
代码
public static List> findContinuesSequence(int target) {
// 至少包含两个数,所以最小也得是3,这样还有{1,2}一个组合满足
if (target < 3) {
return null;
}
// 初始化两个指针
int small = 1;
int big = 2;
// 获取目标值的一半
int middle = (target + 1) / 2;
// 保存结果
List> result = Lists.newArrayList();
// small < middel,因为big比small大,超过middle,small+big > target
// 等于也不可以,small+big>target
// 比如14,middel=7,如果small=7,big > small,small+big > target
// 所以所有结果的起始点应该在middle的左侧
int sum = small + big;
while (small < middle) {
/* 这是自己的写法
int sum = 0;
for (int i = small; i <= big; i++) {
sum += i;
}
if (sum == target) {
result.add(Lists.newArrayList(small, big));
big++;
} else if (sum > target) {
small++;
} else {
big++;
}
*/
// 如果和大于target,则减去较小的值small, 并移动small的指针,使得sum <= target
// sum <= target时,终结此次while
// sum > target时,减小范围,移动small的指针,此时需要减去大于target的部分
// sum = target时,记录此次结果,并且移动big的指针,扩大查找范围
// sum < target时,扩大范围,移动big的指针,此时需要更大的值来弥补和target的差距
// 比如 target = 15, small=1, big = 2
// sum = 1+2 =3, sum < target, small=1, big = 3
// sum = 1+2+3 = 6, sum < target, small=1, big = 4
// sum = 1+2+3+4 = 10, sum < target, small=1, big = 5
// sum = 1+2+3+4+5 = 15, sum = target, 找到, 扩大搜索范围, small=1, big = 6
// sum = 1+2+3+4+5+6 = 21, sum > target, small=2, big = 6
// sum = 2+3+4+5+6 = 20, sum > target, small=3, big = 6
// sum = 3+4+5+6 = 18, sum > target, small=4, big = 6
// sum = 4+5+6 = 15, sum = target, , 找到, 扩大搜索范围, small=4, big = 7
// sum = 4+5+6+7 = 22, sum > target, small=5, big = 7
// sum = 5+6+7 = 18, sum > target, small=6, big = 7
// sum = 6+7 = 13, sum < target, small=6, big = 8
// sum = 6+7+8 = 21, sum > target, small=7, big = 8
// sum = 7+8 = 15, sum = target, , 找到, 扩大搜索范围, small=7, big = 9
// sum = 7+8+9 = 24, sum > target, small=8, big = 9
// middel = (15 + 1) / 2 = 8, 不满足small < middle,退出
while (sum > target && small < middle) {
sum -= small;
small++;
if (sum == target) {
result.add(Lists.newArrayList(small, big));
}
}
big++;
sum += big;
}
return result;
}