剑指Offer57-和为s的连续正数序列-easy

试题链接

题目描述:

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

序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。

例如输入:

输入:target = 9
输出:[[2,3,4],[4,5]]

输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]

数据范围:

1 <= target <= 10^5

解题思路:

尺取法:顾名思义,像尺子一样取一段,借用挑战书上面的话说,尺取法通常是对数组保存一对下标,即所选取的区
间的左右端点,然后根据实际情况不断地推进区间左右端点以得出答案。之所以需要掌握这个技巧,是因为尺取法比
直接暴力枚举区间效率高很多,尤其是数据量大的。
但是尺取法有他的适用情况

  • 要求一个连续区间
  • 有一个总的标准,比如说,连续区间求和满足一个值sum,求一个连续区间内的xx种类
  • 区间长度是弹性的,在满足标准的情况下,推进左右端点,使得区间长度符合要求.

回过头看此题是否满足尺取法的要求呢

  • 连续的正整数序列
  • 标准:正整数序列和满足 target
  • 区间长度是弹性的
    Yes! 满足要求,接下来看算法的流程
    算法流程:
  • 初始化三个变量 i = 1 表示头指针, j = 2 表示尾指针,sum = 1和一个动态数组(vector)tmp.
  • 进入循环
    • 如果 i < j (头指针小于尾指针) 且 sum < target (求和不等于target的值)循环执行
      • sum += j (sum加上尾指针的值)
      • tmp加入j (序列加上尾指针的值)
      • j+=1 (尾指针后移一位)
    • 如果i >=j(头指针大于等于尾指针)
      结束整个循环
    • 如果 sum 等于 target
      • 判断此时tmp的大小,满足大于等于2的话,最后结果集加入此序列
      • tmp删除头指针的值
      • sum-=头指针的值
      • 头指针后移一位
        总的来说,就像一条毛毛虫
        演示一下题目给的用例。
        在这里插入图片描述
        在这里插入图片描述
        在这里插入图片描述
        在这里插入图片描述

AC代码(c++)

class Solution {
    
    
public:
    vector<vector<int> > findContinuousSequence(int target) {
    
    
        vector<vector<int> > arr;
        vector<int> tmp;
        int i=1,j=2;
        int sum = 1;
        tmp.push_back(1);
        while(1){
    
    
            while(i<j && sum<target){
    
    
                sum+=j;
                tmp.push_back(j);
                j++;
            
            }
            if(i>=j)
                break;
            if(sum==target)
            {
    
    
                if(tmp.size()>=2){
    
    
                    arr.push_back(tmp);
                }
                tmp.erase(tmp.begin());
                sum-=i;
                i++;
            }
            while(sum>target){
    
    
                sum-=i;
                i++;
                tmp.erase(tmp.begin());
            }
        }
        return arr;
       
    }
};

猜你喜欢

转载自blog.csdn.net/Yang_1998/article/details/113141180