• 数据结构算法复杂度详解


    算法复杂度问题

    引例

    第一种算法:(1+(n+1)+n)=2n+2次

    int i,sum=0,n=100;      //执行1次
    for(i=1;i<=n;i++){      //   执行n+1词
        sum+=i;             //执行n次
    }
    

    第二种算法: 1+1=2次

    int sum=0,n=100;        //执行1次
    sum=(1+n)*n/2;          //执行1次
    

    如果我们把循环看作一个整体,忽略头尾判断的开销,那么这两个算法就是n和1的差距;
    算法的复杂度,我们侧重的是研究算法随着输入规模的扩大增长量的一个抽象,而不是精确的定位执行了多少次;

    列:

    int i,j,x=0,sum=0,n=100;
    for(i=1;i<=n;i++){      //执行n+1次
        for(j=1;j<=n;j++){  //当外层i每执行1次,内层j执行n+1次
            x++;            //执行n次
            sum=sum+x;
        }
    }
    

    此算法的复杂度就为$n{2}$,也就是$1002$次;

    我们在分析算法的运行时间时,重要的是把基本操作的数量和输入模式关联起来。

    时间复杂度的定义: 在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况确定T(n)的数量级。
    算法的时间复杂度,也就是算法的时间量度,记作:T(n)=O(f(n))。
    它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度,简称为时间复杂度。其中f(n)是问题规模n的某个函数。

    通用攻略:

    用常数1取代运行时间中的所有加法常数。
    在修改后的运行次数函数中,只保留最高阶项。
    如果最高阶项存在且不是1,则除去与这个项相乘的常数。
    得到的最后结果就是大O阶。


    常数阶

    int sum=o,n=100;
    printf("第一条");
    printf("第二条");
    printf("第三条");
    printf("第四条");
    printf("第五条");
    printf("第六条");
    sum = (i+1)*n/2;    //只有这一句影响了n
    

    因为T(n)是关于问题规模n的函数,所以时间复杂度为:O(1)


    线性阶

    int n=100;      
    for(int i=1;i < n;i++){     
        printf("hello guys");   //执行n次          
    }
    

    因为循环体中的代码需要执行n次,所以时间复杂度为:O(n)


    平方阶(1)

    int n=100;
    for(int i=0;i < n;i++){         //执行n次
        for(int j=0;j < n;j++){     //执行n*n次
            printf("hello guys");
        }
    }
    

    因为循环体中的代码需要执行n*n次,所以时间复杂度为:O($n^{2}$)


    平方阶(2)

    int n=100;
    for(int i=0;i< n;i++){          //执行n次
        for(int j=i;j< n;j++){      //当i=n时,j执行n-1次
            printf("hello guys");
        }
    }
    

    分析:

    内循环总的执行次数应该是:
    $-n+(n-1)+(n-2)+...+1=frac{n(n+1)}{2}$
    $frac{n(n+1)}{2}=frac{n^2}{2}+frac{n}{2}$

    根据大O攻略:
    第一条忽略,因为没有常数相加。
    第二条只保留最高项,所以$frac{n}{2}$去掉。
    第三条,去除与最高项相乘的常数,最终得O($n^{2}$)。


    对数阶

    int n=100;
    while(int i<n){
        i=i*2;
    }
    

    由于$2{x}=n$得到$x=log_2{n}$,所以,这个循环的时间复杂度为O($log{n}$)。


    函数时间复杂度分析

    int n=100;
    for(int i=0;i< n;i++){
        function(i);
    }
    void function(int count){
        printf("hello guys");
    }
    

    函数的复杂度是O(1),而for循环的调用,所以时间复杂度是O(n)。

    int n++;
    function(n);
    
    for(int i=0;i< n;i++){
        function(i);
    }
    for(int i=0;i< n;i++){
        for(j=i;j< n;j++){
            printf("hello guys");
        }
    }
    void function(int count){
        printf("hello guys");
    }
    

    $1$+$1$+$n$+$n{2}$=**O($n{2}$)**

    总结:

    O(1) < O($log{n}$) < (n) < O($nlog{n}$) < O($n^2$) < O($n^3$) < O($2^n$) < O($n!$) < O($n^n$)

  • 相关阅读:
    数据科学面试应关注的6个要点
    Python3.9的7个特性
    一种超参数优化技术-Hyperopt
    梯度下降算法在机器学习中的工作原理
    MQ(消息队列)功能介绍
    D. The Number of Pairs 数学
    F. Triangular Paths 思维
    D. XOR-gun 思维和 + 前缀
    C. Basic Diplomacy 思维
    D. Playlist 思维
  • 原文地址:https://www.cnblogs.com/apebro/p/12573574.html
Copyright © 2020-2023  润新知