c++实现面试题57 - II. 和为s的连续正数序列


输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。

序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
在这里插入图片描述

1,暴力法

枚举每个正整数为起点,判断以它为起点的序列和 sum 是否等于target 即可,由于题目要求序列长度至少大于 2 ,所以枚举的上界为 (target-1)/2

class Solution {
public:
    vector<vector<int>> findContinuousSequence(int target) {
        vector<vector<int>> res; //定义二维数组
        vector<int>ans; //定义一维数组
        int sum=0; //初始化求和变量
        int limit = (target-1)/2; //设定上限值
        for(int i=1;i<=limit;i++) //循环遍历
        {
            for(int j=i; j<target;j++)
            {
                sum+=j;
                if(sum > target) //如果大于target,跳出循环
                {
                    sum = 0;
                    break; //终止循环
                }
                else if(sum == target) //如果等于target,将外循环起点至内循环结束点加入一维数组
                {
                    ans.clear();
                    for(int k=i;k<= j;k++)
                    {
                        ans.emplace_back(k);
                    }
                    res.emplace_back(ans); //将一维数组插入二维数组
                    sum = 0; //清空求和变量
                    break; //跳出循环,执行下一个外循环。
                }
            }
        }
        return res;

    }
};

2,滑动窗口

将target看成一个等差排列的数组[1,2,3,4,5,6,7,8,9…],滑动窗口就是在数组中框选一部分,然后向右滑动。

我们设滑动窗口的左边界为 i,右边界为 j,则滑动窗口框起来的是一个**左闭右开区间 [i, j)**在一开始,i=1, j=1,滑动窗口位于序列的最左侧,窗口大小为零。

滑动窗口的重要性质是:窗口的左边界和右边界永远只能向右移动,而不能向左移动。
当滑动窗口的右边界向右移动时,也就是 j = j + 1,窗口中多了一个数字 j,窗口的和也就要加上 j。当滑动窗口的左边界向右移动时,也就是 i = i + 1,窗口中少了一个数字 i,窗口的和也就要减去 i

class Solution {
public:
    vector<vector<int>> findContinuousSequence(int target) {
        int i = 1; //定义滑动窗口的左边界
        int j = 1; //定义滑动窗口的右边界
        int sum = 0; //初始化累加和
        vector<vector<int>> ans; //定义二维数组
        while(i <= target/2)
        {
            if(sum < target) //如果sum>target,sum累加右边界值,并且右边界往右滑动一单位
            {
                sum += j;
                j++;
            }
            else if(sum > target) //如果sum<target,sum减去左边界值,并且左边界向右滑动一单元
            {
                sum -= i;
                i++;
            }
            else //如果sum=target
            {
                vector<int> nums; //定义一个一维数组
                for(int k = i;k<j;k++) //循环遍历窗口
                {
                    nums.push_back(k); //把每个数据插入nums数组
                }
                ans.push_back(nums); //把nums数组插入ans二维数组
                sum = sum- 2*i - 1 ;  //当sum==target时,左边界移动一单元必定无解,所以i要移动两个单位,sum也要减少相应两个单位对应的值
                i+=2;
            }
        }
        return ans;

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值