zoukankan      html  css  js  c++  java
  • 时间复杂度和空间复杂度1

    算法效率的度量方法

    事后统计方法

    通过设计好的测试程序和数据,利用计算机计时器对不用算法编制的程序的运行时间进行比较,从而确定算法的高低

    缺陷:

    1. 事先编制好程序,花费大量时间和精力
    2. 时间的计算依赖计算机硬件和软件等环境因素
    3. 算法的测试数据设计困境

    事前分析估算方法

    在计算程序编制前,依据统计方法对算法进行估算

    取决因素:

    1. 算法才用的策略、方法
    2. 编译产生的代码质量
    3. 问题输入规模
    4. 机器执行指令速度

    一个程序的运行时间,取决于算法的好坏和问题的输入规模(输入量的多少)

    例子:

    第一个算法:

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

    第二种算法:

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

    第一种算法执行了1 + (n +1)+ n+1 次 = 2n+3次

    第二种算法执行 1 +1+1 = 3次

    如果把循环看作一个整体,忽略头尾循环判断的开销,那么这个两个算法其实就是n次和1次的差距

    例子:

    int i,j, x=0, sum=0, n=100; //执行1次
    for(i=1; i<=n; i++) 
    {
      for(j=i; j<=n; j++) 
    	{
        x++
      	sum = sum + x; 		//执行n * n次
      }
    }
    prinf("%d", sum) //执行1次
    

    从这个例子中,i从1到100,每次都有让j循环100次,而当中x++ 和sum= sum+x;其实就是1+2+3+...+10000, 也就是1002次;循环整体n2,显然算法执行次数与输入规模n=100有关系,算法执行时间随着n的增加也变长

    因此,测试运行时间最可靠方法:计算对运行时间有消耗的基本操作次数;运行时间与这个计数成正比

    我们不关心编写程序所用的编程设计语言是什么,不关心程序跑在什么计算机中,值关心实现算法,

    不计哪些循环所用的递增和循环终止条件,变量声明,打印结果等操作,最终,在分析程序运行时间时,最重要的事把程序看成独立与程序设计语言的算法或以一系列步骤

    分析一个算法的运行时间,重要的事基本操作的数量和输入规模关联起来,即基本操作的数量必须表示输入规模的函数

    函数的将近增长

    先判断两个算法A和B哪个更好?

    前提:两个算法输入规模都是n

    算法A:2n+3次操作

    算法B:3n+1次操作

    规模 算法A1(2n+3) 算法A2(2n) 算法B1(3n+1) 算法B2(3n)
    n=1 5 2 4 3
    n=2 7 4 7 6
    n=3 9 6 10 9
    n=10 23 20 31 30
    n=100 203 200 301 300

    分析:

    • 当n=1时,算法A1效率不如算法B1
    • 当n=2时,算法A1效率与算法B1相同
    • 当n>2时,算法A1优于算法B1

    总体上算法A比算法B优秀

    定义

    给定两个函数f(n)和g(n),如果存在一个整数N,使得对于所有n > N, f(n)总是比g(n)大,那么,我们说f(n)的增长渐近快于g(n)

    第一个例子

    随着n的增大,算法后面+3和+1不会影响最终算法的变化,因此可以忽略这些算法的常数

    第二个例子:

    规模 算法C(4n+8) 算法C1(n) 算法D(2n^2+1) 算法D2(n^2)
    n=1 12 1 3 1
    n=2 16 2 9 4
    n=3 20 3 19 9
    n=10 48 10 201 100
    n=100 408 100 20001 10000
    n=1000 4008 1000 2000001 1000000

    当n<=3时,算法C要差月算法D, 当n>3后,算法C的优势越来越优于算法D, 去掉与n相乘的常数,结果也没变化

    ,与最高次项相乘的常数并不重要

    第三个例子:

    算法E是 2n^2+3n+1, 算法F是2n^3+3n+1

    规模 算法E(2n^2+3n+1) 算法E1(n^2) 算法F(2n^3+3n+1) 算法F2(n^3)
    n=1 6 1 6 1
    n=2 15 4 23 8
    n=3 28 9 64 27
    n=10 231 100 2031 1000
    n=100 20301 10000 2000301 1000000

    当n=1时,算法E与算法F结果相同

    当n>1后,算法E优势就开始优于算法F,随着n的增大,差异非常明显

    最高次项的指数大的,函数随着n的增大,结果也会变得增大特别快

    最后一个例子

    算法G:2n^2

    算法H: 3n+1

    算法I: 2n^2+3n+1

    规模 算法G(2n^21) 算法H(3n+1) 算法I(2n^3+3n+1)
    n=1 2 4 6
    n=2 8 7 15
    n=5 50 16 66
    n=10 200 31 2031
    n=100 20000 301 20301

    当n的值越来越大时,3n+1已经无法与2n^2比较,算法G的结果趋于算法I

    判断一个算法效率时,函数中的常数和其他次要项常常可以忽略,更应该关注(最高阶项)的阶数

    某个算法,随着n的增大,它会越来越优于另一个算法,或者越来越差另一个算法

  • 相关阅读:
    c++实现单例
    shell查看并修复网络连接
    shell检测interface是否已分配ip,qt调用shell脚本
    ubuntu, Debian, CentOS
    Makefile 中:= ?= += =的区别
    我开新博客了
    soft lockup和hard lockup介绍
    linux系统奔溃之vmcore:kdump 的亲密战友 crash
    布局文件中的sp、dp还有px的区别
    kvmalloc函数
  • 原文地址:https://www.cnblogs.com/smallyi/p/14426030.html
Copyright © 2011-2022 走看看