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;
        }
    };
    
  • 相关阅读:
    windows 7下matlab R2010a输入乱码的解决方案
    用 Microsoft Visual C++ 创建一个使用 wpcap.dll 的应用程序,
    E: oss4dkms: 子进程 脚本出错postinstallation 安装升级更新时出错的解决方法
    关于linux下面挂载Windows硬盘,但是无法在Windows下看到数据
    如何读取多个文件,文件后缀名不一致,不过类似source.1 source.2 source.3等
    Fedora 12 13 14基础环境配置
    linux内核空间与用户空间信息交互方法
    HDU 1232 畅通工程(最小生成树+并查集)
    hdu 2647 Reward(拓扑排序,反着来)
    HDU 1532 Drainage Ditches (最大网络流)
  • 原文地址:https://www.cnblogs.com/whiteBear/p/12618391.html
Copyright © 2011-2022 走看看