c++实现---和为s的连续正数序列

题目:
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
方法一:暴力方法
求和为sum的连续子序列,可用暴力方法,
算法步骤:
用指针i枚举目标序列的左边界
用指针j枚举目标序列的右边界
用指针k枚举区间[i, j],来计算区间和,看是否等于目标sum。
代码如下:

class Solution {
public:
 vector<vector<int> > FindContinuousSequence(int sum) {
     vector<vector<int>> ret;
     // 左边界
     for (int i=1; i<=sum/2; ++i) { 
         // 右边界
         for (int j=i+1; j<sum; ++j) {
             int tmp = 0;
             // 求区间和
             for (int k = i; k<=j; ++k) {
                 tmp += k;
             }
             if (sum == tmp) {
                 vector<int> ans;
                 for (int k=i; k<=j; ++k) ans.push_back(k);
                 ret.push_back(ans);
             }
             else if (tmp > sum) {
                 break;
             }
         }
     }
     return ret;
 }
};

时间复杂度:O(N^3)
空间复杂度:O(1)
方法二:滑动窗口
滑动窗口的操作
扩大窗口,j += 1
缩小窗口,i += 1
算法步骤:
初始化,i=1,j=1, 表示窗口大小为0
如果窗口中值的和小于目标值sum, 表示需要扩大窗口,j += 1
否则,如果狂口值和大于目标值sum,表示需要缩小窗口,i += 1
否则,等于目标值,存结果,缩小窗口,继续进行步骤2,3,4
代码如下:

class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
        vector<vector<int>> help;
        if(sum<3) return help;//至少两个数,没有两个正数的和小于3
        int l=1,r=1;
        int tmp=0;
        while(l<=sum/2){
            if(tmp<sum){//如果累加和小于sum,增加r
                tmp+=r;
                ++r;
            }else if(tmp>sum){//如果累加和大于sum,则需要删去序列中的一些数字,增加l
                tmp-=l;
                ++l;
            }else{
                vector<int> ans;
                for(int i=l;i<r;++i){
                    ans.push_back(i);
                }
                help.push_back(ans);
                
                tmp-=l;//当前序列满足后,继续从左边删除,开始后移
                ++l;
            }
        }
        return help;
    }
};

时间复杂度:O(N)
空间复杂度:O(1)

猜你喜欢

转载自blog.csdn.net/Fizz6018/article/details/107216662