zoukankan      html  css  js  c++  java
  • 如何高效的找到所有总和为 sn 的连续正整数数列。

    例如 sn = 100 时,总和为100 的连续正整数数列有

    100
    18 19 20 21 22
    9 10 11 12 13 14 15 16

    对于这种算法的设计,我们最容易想到的就是从 1 到 sn 循环遍历所有的数,对于每个数再循环计算是否以这个数为起点总和正好是sn。这种算法的时间复杂度大概是

    O(n*log2n), 也就是说如果这样计算,当 sn = 100万时,大概需要循环 2000万次左右。 这样做效率自然是比较低的。那么我们有没有比上述方法更高效的方法呢?答案是肯定的。

    首先我们看等差数列求和的公式:

    Sn=n(a1+an)/2=na1+n(n-1)/2

    从这个公式我们不难看出当 Sn 和 n  固定时求a1 是一个线性函数:

    a1 = (Sn – n(n-1)/2) / n

    有了这个函数,优化这个算法就很简单了,我们只要把 n  从 1 开始遍历,一直遍历到 (Sn – n(n-1)/2) < n 为止,就可以找到所有的符合条件的连续数列了,这个算法的算法复杂度为 2N 的平方根,也就是说当 Sn = 100 万时,只需要循环1414次就可以得到所有的数列。

    刚刚看到邀月的算法:  http://www.cnblogs.com/downmoon/archive/2011/03/05/1971400.html

    这个算法 sn = 100 万时,循环次数是 12970034 次,比我这个算法效率上要低将近1万倍。

    下面给出我的算法代码

            static void ListSequence(int sn)
            {
                //忽略 sn 不是正整数的情况
                if (sn <= 0)
                {
                    return;
                }
     
                int n = 1; //n 从1 开始遍历
     
                int m = sn - n * (n - 1) / 2; //m 为 Sn – n(n-1)/2
     
                while (m >= n) //当m < n 时即 Sn – n(n-1)/2 < n 时退出循环
                {
                    if (m % n == 0) //如果m 可以被 n 整除,则存在连续n个正整数序列总和为sn。
                    {
                        int a1 = m / n; //求a1
     
                        //打印符合条件的连续数列
                        for (int i = a1; i < a1 + n; i++)
                        {
                            Console.Write(string.Format("{0} ", i));
                        }
                        Console.WriteLine();
                    }
     
                    n++; //n 加1
                    m = sn - n * (n - 1) / 2; //下一个 m
                }
     
                Console.WriteLine("循环次数:{0}", n);
            }

    Sn = 100 时,运行结果:

    100
    18 19 20 21 22
    9 10 11 12 13 14 15 16
    循环次数:14

    下面给出 Sn 从 10 开始到 1000万时的循环次数。

    Sn 循环次数
    10 5
    100 14
    1000 45
    10000 141
    100000 447
    1000000 1414
    10000000 4472
  • 相关阅读:
    一步一步搭建客服系统 (4) 客户列表
    一步一步搭建客服系统 (3) js 实现“截图粘贴”及“生成网页缩略图”
    【Servlet】深入浅出JavaServlet重定向和请求转发
    【java】深入了解JAVA可变长度的参数
    【HTML】网页中如何让DIV在网页滚动到特定位置时出现
    【HTML】 向网页<Title></Title>中插入图片以及跑马灯
    【JQuery】jQuery中的常用方法小结
    【JQuery】jQuery(document).ready(function($) { });的几种表示方法及load和ready的区别
    【JQuery】jquery对象和javascript对象即DOM对象相互转换
    【javascript】javascript中function(){},function(){}(),new function(){},new Function()
  • 原文地址:https://www.cnblogs.com/eaglet/p/1971391.html
Copyright © 2011-2022 走看看