和为S的连续正数序列

时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M

题目描述

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

输出描述:

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

思路:

  • 在该题讨论区中发现了这种思路,采用了所谓的双指针技术,相当于有了个窗口,窗口的左右两边就是两个指针,根据窗口内数值和的情况来确定窗口的位置以及宽度。

比如:

输入sum = 20,遍历1,2,3,...,18,19,20

  1. 定义两个指针leftP,rightP,左指针leftP指向1,右指针rightP指向2,先固定leftP不动,rightP依次往后遍历求和sumVal,直到rightP的值大于sum的值,遍历循环结束
  2. 当sumVal < sum :rightP++,并sumVal加上当前值;当sumVal > sum时:要先sumVal减去leftP,再leftP++更新leftP数据;当sumVal == sum:则将leftP和rightP这个区间内的数值存储到vector容器中;
  3. 要求输出所有的和为S的连续正序列,则仍需要继续往下进行。rightP++,sumVal+=rightP,直到循环条件不满足
class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
         vector<vector<int>> saveRe;
        if(sum <= 0)
            return saveRe;
        int leftP = 1;
        int rightP = 2;
        int sumVal = leftP + rightP;
        while(sum > rightP)
        {
            if(sumVal < sum)
            {
                rightP++;
                sumVal += rightP;
            }
            else if(sumVal > sum)
            {
                sumVal -= leftP;
                leftP++;
            }
            else
            {
                vector<int> saveElem;
                for(int i = leftP;i <= rightP;i++)
                {
                    saveElem.push_back(i);
                }
                saveRe.push_back(saveElem);
               rightP++;
                sumVal += rightP;
            }
        }
        return saveRe;
    }
};

  • 另一种解法虽然也是使用了双指针,但巧妙之处在于总结道该连续数列为公差为1的等差数列,因此利用等差数列的求和公式,使代码更加简洁、清晰,也再次体现出数学的魅力
class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
         vector<vector<int>> saveRe;
        if(sum <= 0)
            return saveRe;
        int leftP = 1;
        int rightP = 2;
        while(leftP < rightP)
        {
            //由于是连续的,差为1的一个序列,那么求和公式是(a0+an)*n/2
            int sumVal = (leftP+rightP)*(rightP - leftP +1)/2;
            if(sumVal < sum)
            {
                rightP++;
            }
            else if(sumVal > sum)
            {
                leftP++;
            }
            else
            {
                vector<int> saveElem;
                for(int i = leftP;i <= rightP;i++)
                {
                    saveElem.push_back(i);
                }
                saveRe.push_back(saveElem);
               rightP++;
            }
        }
        return saveRe;
    }
};
posted @ 2020-04-02 11:17  牛犁heart  阅读(166)  评论(0编辑  收藏  举报