题目描述
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
这个是个纯公式题,也可以采取暴力法解决,
公式如下:
设连续数列长度为n
开始节点为a
结束节点为b
那么由等差公式得
(a + b)/ 2 * n = sum =》 (a + b) * n = sum * 2
又因为
b - a = n -1
(a + b) * n = sum * 2
所以有两个方程,三个未知数
只要我们遍历n的值去试探方程的整数解即可得出a和b的值
例如 sum = 100
n = 2时,b - a = 1 , a + b = 100 a, b没有正整数解,所以不符合要求跳过
n = 8时,b - a = 7, a + b = 25 a = 9 b =16 即 9- 16连续子串的和为100
实现如下:
#pragma once
#include <vector>
using namespace std;
namespace sum_100_number
{
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum)
{
int n = 2;
vector<vector<int> > vv;
if (sum <= 2)
return vv;
for (int n = sum; n >= 2; n--)
{
if (sum * 2 % n == 0)
{
int h = sum * 2 / n;
int c = n - 1;
int an = (h + c) % 2 == 0 ? (h + c) / 2 : -1;
int a1 = (h - c) % 2 == 0 ? (h - c) / 2 : -1;
if (an == -1 || a1 == -1 || a1 <= 0)
{
continue;
}
else
{
vector<int> v;
for (int i = a1; i <= an; i++)
{
v.push_back(i);
}
vv.push_back(v);
}
}
}
return vv;
}
};
}
test.cpp
#pragma once
#include "sum_100_number.h"
namespace sum_100_number
{
void start_test()
{
Solution s;
auto c = s.FindContinuousSequence(100);
}
}
二、其他解法
还有一种思路,就是双指针,组成一个滑动窗口,初始化时,pow 和 high滑动窗口为0,1,如果和小于那么sum
high++,继续计算和,如果大于sum那么pow++,直到和等于sum,再找下一个。
可能这为正解,不然为何公式法要逆序查找