题目描述:
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列,序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
本题知识点:
穷举
解题思路:
- 根据题意,我们可以认为求一个数S为一个等差数列的和,这个的中间值代表了这个数列的平均值。而平均值可以根据(S/n)得到,所以我们只需要确定n值就可以了。但是n值需要一个范围,根据等差数列求和公式,可以得到n的范围,例如S=100,n只需要从2到13进行计算就可以了。当n为奇数时,中间值为序列的平均值,满足S%n==0。当n为偶数时,序列中间的两个值为平均值左右两侧的值,平均值小数部分为0.5,满足(S%n)*2==n。对n从大到小遍历,就可以得到最终结果。
- 采用双指针的方法,两个指针指向的数中间部分即为序列,序列和为S。初始指针设置为1和2,利用等差数列求和公式计算指针中间序列的和,如果和大于S,则将左边的指针向右移一位,若小于S,则将右边的指针向右移一位,若等于S,则将范围内的序列存放到结果中。
代码:
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int> > result;
if(sum < 3)
return result;
int num = (sqrt(8 * sum + 1) + 1) / 2;
num--;
for(int i = num; i > 1; i--)
{
vector<int> temp;
if(i % 2 == 1)
{
if(sum % i == 0)
{
int begin = (sum / i) - (i / 2);
int end = (sum / i) + (i / 2);
for(int j = begin; j < end + 1; j++)
temp.push_back(j);
result.push_back(temp);
}
}
else
{
if((sum % i) * 2 == i)
{
int begin = (sum / i) - (i / 2) + 1;
int end = (sum / i) + (i / 2);
for(int j = begin; j <= end; j++)
temp.push_back(j);
result.push_back(temp);
}
}
}
return result;
}
};