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;
        }
    };
    
  • 相关阅读:
    李洪强经典面试题27
    李洪强经典面试题26(选择题)
    java中InputStream String
    [Android]Android5.0实现静默接听电话功能
    Please verify that your device’s clock is properly set, and that your signing certificate is not exp
    CentOS7虚拟机桥接设置及问题
    GuozhongCrawler系列教程 (5) TransactionRequest具体解释
    js之substr和substring的差别
    hdu 3549 Flow Problem
    JSP与HTML的差别
  • 原文地址:https://www.cnblogs.com/whiteBear/p/12618391.html
Copyright © 2011-2022 走看看