zoukankan      html  css  js  c++  java
  • 和为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;
        }
    };
    
  • 相关阅读:
    【学习笔记】ASP.NET页面之间传值的方式之Application
    【学习笔记】ASP.NET页面之间传值的方式之QueryString
    【学习笔记】C#中的装箱(inboxing)和拆箱(unboxing)
    C# Func和Action用法以及区别和使用Lambda表达式
    构建ABP vNext项目并切换MySql数据库
    .Net FrameWork发布项目时报Microsoft.Net.Compilers is only supported on MSBuild v16.3 and above错误解决方案
    Docker容器与Linux主机环境获取时间不一致
    shell脚本中无法使用cd的问题解决方法
    Docker安装Mysql8.0,并配置忽略大小写
    Docker-Compose排版一些坑
  • 原文地址:https://www.cnblogs.com/whiteBear/p/12618391.html
Copyright © 2011-2022 走看看