笔记:复杂度分析(上)

前言

众所周知,之所以引入数据结构和算法,是为了让我们的程序更加地健壮,更“快”、更“省”。那么,怎么去考量一个算法的执行效率呢,那就是今天的主角:复杂度分析。

什么是复杂度分析

复杂度也叫渐进复杂度,是指算法在编写成可执行程序后,运行时所需要的资源,包括时间资源和空间资源(内存资源),所谓的分析就是用来分析算法执行效率和数据规模之间的增长关系,可以这么说越高阶复杂度的算法,执行效率越低。

为什么需要复杂度分析

你可能会这么想:我把自己写的代码跑一边,然后看看执行时间和内存使用情况不就知道自己写的如何了吗。

这么操作是没有问题的,但是这种方法有非常大的局限性。

依赖测试环境

如果通过执行结果来分析的话,在不同设备上,不同内存,不同cpu的情况下,测试的结果就会出现很大的差异。

依赖数据规模

如果通过上述方法来检测代码的健壮性,需要大量的测试,对于数据的规模有很大要求。

和性能测试相比,复杂度分析有不依赖执行环境、成本低、效率高等特点。 掌握好复杂度分析,将编写出更加优质的代码。

如何进行复杂度分析
大O表示法

举一个累加的例子:

void add (int n) {
  int sum = 0;
  for(int i = 1 i <=n; i++) {
    sum+=i
  }
  return sum;
}
复制代码

我们来分析下这段代码的执行时间,用T(n) 表示执行的总时间,x表示每行代码执行的时间,可以得出:

T(n) = (n+ 1)x
复制代码

当n越大,所执行的时间就越久,可以看出:执行时间和代码的执行次数n成正比

总结一下:

 T(n) = O(f(n))
复制代码

f(n)表示每行代码的执行次数总和,用一个公式表示。O表示执行时间和公式成正比

当n无限大时,公式中的常量和低阶的部分就可以忽略掉,所以上述代码的执行时间T(n) = O(n)

复杂度分析法则
  1. 单段代码看高频 比如上面例子的 循环
  2. 多段代码取最大 举个例子:
void add (int n) {
  int sum1 = 0;
  for(int i =1;i <= 50; i ++) {
    sum1+=i;
  }
  
  sum2 = 0;
  for(int j = 1;j <= n; j++) {
    sum2+=j;
  }
  sum3 = 0;
  for(int m = 1; m <=n; m ++) {
    for(int s = 1; s <=n; s++) {
      sum3+=s;
    }
  }
  return sum1+sum2+sum3;
}
复制代码

这是一个多段代码,有三个片段,时间复杂度分别是:50,n,n*n 取最大的复杂度就是 T(n) = O(n**n) 3. 嵌套代码求乘积:比如上述例子中的最后一个片段。 4. 多个规模求加法 再举个栗子:

void add (int n, int m) {
  sum1 = 0;
  for(int i = 1; i <=n; i ++) {
    sum1+=i;
  }
  sum2 = 0;
  for(int j = 1; j <=m; j++) {
    sum2+=j;
  }
  return sum1 + sum2;
}
复制代码

该代码的执行时间 T(n) = O(n + m)

时间复杂度和空间复杂度
时间复杂度

上述代码的执行时间都是一中时间复杂度,也叫渐进式时间复杂度,表示代码执行时间随着数据规模增长的变化趋势。

空间复杂度

空间复杂度,也叫渐进式空间复杂度,表示算法的存储空间与数据规模之间的增长关系。

  int i = 0;
  int [] a = new int [n]
复制代码

可以看出第2行代码开辟了大小为n的空间,所以空间复杂度为O(n)

常用复杂度级别

虽然代码千差万别,但是大致分为一下几种: 根据数量级递增可以分为两类:多项式量级非多项式量级

多项式量级:随着数据规模的增长,算法的执行时间和空间占用,按照多项式的比例增加。包括:

O(1) 常数阶                O(logn) 对数阶
O(n) 线性阶                O(nlogn) 线性对数阶
O(n^2) 平方阶              O(n ^3) 立方阶
复制代码

O(1)

int i = 5;
int j = i +6;
复制代码

像上面这段代码的复杂度就是O(1),只要f(n)是一个常量,就是O(1)

非多项式量级:随着数据规模的增加,算法的执行时间和空间占用暴增,这类算法性能差。包括:

O(2^n) 指数阶              O(n!)阶乘阶
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值