• [计算机漫谈]算法运行时间估计及素数判断算法


        大家好!这是我的第一篇博文,谢谢大家的支持!

       (一)算法运行时间估计

       估计某个算法的时间复杂度需要一些数学定义,如   T(N) = O(fn),表示T(N)的增长率小于等于fn;    T(N) = Ω(fn),表示T(N)的增长率大于fn;    T(N) = θ(fn),表示T(N)的增长率等于fn;    T(N) = o(fn),表示T(N)的增长率小于fn. 我们一般考察O,即大O,时间上界.一个算法运行的时间进行估计,以便我们更好的了解程序设计与运行的优化方法.

       

      估计法则1:

           如果T1(N) = O(fn),t2(N) = O(gn),则有 T1(N)+T2(N) = max(O(fn),O(gn)) ,T1(N)*T2(N) = O(fn*gn)

       估计法则2(循环):

          一次循环的运行时间至多是循环体内语句运行时间乘以循环次数;嵌套循环为循环体内语句运行时间乘以各层循环次数之积.

       估计法则3(顺序结构):

          顺序结构运行时间等于各条语句运行时间之和.

       估计法则4(分支结构):

         分支结构运行时间不会大于分支中运行时间最长的那个分支体.

       估计法则5(对数):

         对数形式一般出现在 一个算法用常数时间将问题大小削减一半(或者有形如k *= 2的形式), 如二分查找

     

      综合以上法则,我们就可以分析出某个具体算法的时间上界

     例:分析运行时间

        

    1 Value = 0;
    2    for( i= 1; i < N; i++)
    4      for( j = 1;j < i*i; j++)
    6          for( k = 0; k < j; k++)
    8                    Value++;

         Value++的运行时间为常数阶,第一层循环次数为N;第二层循环次数i*i与N2   有关,因为i与N有关.同理第三层循环次数j与N2 有关.则N*N2 *N2=N5,即O(N5)

       (二)素数判断算法

        在程序设计的学习过程中,判断一个数是否为素数的算法相信大家都非常熟悉了,这里与大家复习一下并提出更好的方案.

        首先,什么是素数.素数就是除了1和它本身外,没有其他因数的正整数.啊,将n从2除到√n,这是我的,相信也是很多人的第一想法.那么有没有更好的方案呐?让我们从头开始.

        尝试1:

    1 bool isPrime(int n){
    2 if(n <= 1)
    3       return false;                              //1以及非正数不可能为素数,函数返回
    4 for(int i = 2; i < n; i++){                  //从2开始找到n-1
    5      if(n%i == 0)
    6       return false;                   //被整除代表有其他因数,这不是素数,函数返回
    7 }
    8       return true;                               //检验完毕,为素数,函数返回
    9 }

      这是最原始的算法,根据素数定义.容易得到,最坏情况比较要进行n-2次,时间复杂度为O(n).对于判断一个大数的情况,显然费时.

      尝试2:

    1 bool isPrime(int n){
    2  if(n <= 1)
    3       return false;
    4 for(int i = 2; i <= (n/2); i++){
    5      if(n%i == 0)
    6       return false;
    7 }
    8       return true;
    9 }

     因为一个数的因数总是成对出现(如2*3=6,2和3都是6的因数),且按这个数的中值对称分布,因此只需要算到这个数的一半就行了.显然,循环比较次数比尝试1少,但时间复杂度仍为O(n).

     尝试3:

    1 bool isPrime(int n){
    2  if(n <= 1)
    3      return false;
    4 for(int i = 2; i <= sqrt(n); i++){
    5    if(n%i == 0)
    6      return false;
    7 }
    8      return true;
    9 }

    这个方法相信大家非常熟悉,也是最容易想到的.依据是若n有因数a和b,即n=a*b,那么必有一个因数位于2到√n之间,又因因数对称且成对出现,那么检验范围从2到√n就行了(我们当然可以检验√n到n-1),时间复杂度为O(√n)

    尝试4:

     1 bool isPrime(int n){
     2  if(n == 2)                                 //2是偶数中唯一的素数
     3     return true;
     4  if(n <= 1 || n%2 == 0)           //除了2外,所有偶数都不是素数,至少有因数2
     5     return false;
     6 for(int i = 3; i <= sqrt(n); i+=2){
     7   if(n%i == 0)
     8     return false;
     9 }
    10     return true;
    11 }

    注释说的很清楚了.这个算法比尝试3进一步减少了检验比较次数,时间复杂度为O(√n)

    除了上面这些基本尝试(特别是尝试4,比较不错了)外,还有其他算法,如使用素数表的拉宾米勒测试等,还有些算法就需要很多的数学知识了,额.

    书籍推荐:

    谢谢大家!转载请注明出处,谢谢合作!

  • 相关阅读:
    ubuntu9.10在AMD 双核上的安装
    修改wamp默认安装下MySQL的root账户密码
    IE6 IE7 IE8 火狐浏览器兼容问题
    在windows xp下安装ubuntu9.10
    制作Ubuntu U 盘启动盘在ubuntu12.04中
    使用StackTraceElement封装,打印调试代码!
    String字符串拼接原理剖析
    List中的数据如何根据对象的某一个或多个字段排序引出Comparable和comparator的使用
    String类的split方法
    通过例子看六种异常处理的陋习
  • 原文地址:https://www.cnblogs.com/Agent-YRBlogs/p/5971267.html
Copyright © 2020-2023  润新知