41. 和为S的连续正数序列

题目描述:

小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!

输出描述:输出所有和为S的连续正数序列。序列内按照从小到大的顺序,序列间按照开始数字从小到大的顺序。

思路:

要求的是连续正数序列,长度为n,和为sum。

那么可以先求出序列的平均数,即sum/n。

如果n为奇数,那么平均数就是序列正中间的数值;如果n为偶数,那么平均数为序列正中间的两个数字的平均数值,知道了位于中间位置的数字,又知道序列的长度,就可以知道整个序列了。那么符合条件的n为:

1)n为奇数:(n&1) == 1 && sum%n == 0

2)n为偶数:平均数的小数部分为 .5,可知(sum%n) * 2 == n

根据输出描述:序列间按照数字从小到大的顺序,所以前面的序列的开始数字小,那么序列长度就长。因此,可以从前往后遍历n,找到符合条件的n之后,就计算中间值,然后根据序列长度n计算出序列的最开始的值,这样就找到一个序列啦。

但是n最大取多少呢:如果想要n最大,那么序列的开始元素为1,长度为n,那么最后一个元素就是n。

等差数列求和公式n*(1+n)/2 = sum,可得n < sqrt(2*sum);所以最大长度为int sqrt(2*sum)。

再根据题目描述,序列长度n>=2,现在序列的长度的范围已经确定了,可以进行编程了。

class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
        vector<vector<int> > List;
        int endN = sqrt(2 * sum);
        for(int n = endN; n >= 2; -- n)
        {
            if(((n&1)==1 && sum%n== 0) || (sum%n)*2 == n)
            {
                vector<int> tempList;
                for(int i = 0, j = sum/n - (n-1)/2; i < n; ++ i, ++ j)
                    tempList.push_back(j);
                List.push_back(tempList);
            }
        }
        return List;
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_39605679/article/details/81393206