zoukankan      html  css  js  c++  java
  • 复杂度分析(一)

      (一) 复杂度分析的由来

         我们平时写代码的时候,想要知道一段代码的运行时间,占用空间等等,一般都是在代码开始的记录一下当前时间,运行结束的时候,再记录一下时间,最后得出这段代码的运行时间,一般就是通过这个来判断我们的代码的执行效率。这种做法没有错,但是这样做统计出来的。

          在我之前写业务代码的时候,比如增删查改的时候,我经常都是这么干的,为了让一个查询更快,更有效率,边调试,边分析,找出慢的步骤,再逐一解决。那么问题来了,我们还需要学这个算法的时间复杂度分析吗?

          对于这个问题,之前我也是很茫然,看到算法时间复杂度分析的相关内容,我就直接忽略,想着工作中也不会这么分析。

          那么,我先解释一下,上面这种做法有什么弊端呢(其实上面的做法,真心还行)。 1、我们通过这种代码得出来的运行时间是很依靠机器的硬件的,要看你CPU的计算能力,内存的大小等等(不是很多时候,都会有这么一个情况,线下测试很快,线上慢成狗了,因为没有考虑到CPU的分配情况,内存占用情况)。2、这种统计方法受到数据规模的影响很大,在测试环境,测得再OK,上线之后还是问题很大)。

         基于上面这些问题,IT的大牛们,就想了一下,要不对算法的时间复杂度来个抽象,不要依赖于机器,硬件等等做法呢。所以他们就提出了一种做法就做O(n),时间复杂度做法。

     (二)什么是时间复杂度O(n)

          时间复杂度:它并不是表示代码的真正运行时间,而是表示代码的执行时间随数据规模增长的变化情况。

          下面来看这个例子。

        int GetSum(int n)
        {
        1       var sum = 0;
        2       for (var i = 0; i < n; i++)
                {
        3             sum += i;
                }
                return sum;
       }

             我们知道每个语句的执行操作,从CPU的角度来看,就是读数据--运算--写数据,假设这整个操作需要一个单位的时间。我们假设一行代码就是一个单位的执行时间,那么这段代码就是2+2n个单位时间,从这里可以看出来程序的执行时间是和n成正比的。我们把这个规律总结成为一个公式,就是我们的时间复杂度。

        (三)时间复杂度的分析方法

              1、关注执行次数最多的那段代码,那个就是这整段代码的时间复杂度

              2、乘法法则,两个时间复杂度相乘,就是整个时间复杂度。(嵌套内外代码的复杂度等于内外复杂度的乘积)

              3、总的复杂度等于最大的那个复杂度。(一般两个复杂度,不是同一个层级的时候,才取最大的,比如o(n)和o(n2),则取o(n2),如果一个是o(n),另外一个是o(m),则时间复杂度就是o(m+n))

          (四)总结

               感觉这个时间复杂度分析,就像设计模式,你说按照设计模式写出来的代码,也不一定是最好的。我们时间复杂度也是一样,也不一定说o(n)就比o(n2)的好,但是只要当我们一提到某某某设计模式的时候,心里马上就可以勾勒出这个设计模式的代码组成结构。当我们一说o(n)的时候,也可以知道这段代码是如何组织的。

              还有很多常见的时间复杂度,比如o(1),o(n) o(logn) o(nlogn),o(n2)。下面说说我觉得最难分析的o(logn)这个时间复杂度把。

      int GetSum(int n)
      {
                var i = 1;
                while (i<=n)
                {
                    i = i*2;
                }
                return i;
      }

            上面这个例子,一步步来分析,i=2,I=4,i=8,i=16,一直到i<=n。  那这个代码执行了多次呢。就是2的x次方小于等于n。 现在要求这个x是多少呢,那就用到我们的对数了x=log2为底,n为真数的对数了。

         int GetSum(int n)
            {
                var i = 1;
                while (i<=n)
                {
                    i = i*3;
                }
                return i;
            }

            这个例子也是和上面是一样的,它是Log3为底,n为真数的对数。

            我们知道对数是可以相互转化的了 。对数都是可以相互转化的,我们同时把他们转化为以十为底的对数,然后去掉常量,就得到了o(logn)。然后o(nlogn)就是n个o(logn)相乘。

             

              

  • 相关阅读:
    STL目录
    Hola!
    SWPUCTF 2019总结以及部分WP
    SQL手工注入基础篇
    JDK11,JDK12没有JRE的解决方法
    FJUT2019暑假周赛三部分题解
    FJUT2019暑假周赛一题解
    随笔1
    关于针对本校教务系统漏洞的一次信息检索
    KMP算法讲解
  • 原文地址:https://www.cnblogs.com/gdouzz/p/9950479.html
Copyright © 2011-2022 走看看