算法的时间复杂度和空间复杂度

1,832 阅读2分钟

算法是什么

算法(Algorithm)是指用来操作数据、解决程序问题的一组方法。对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,但在过程中消耗的资源和时间却会有很大的区别。

衡量算法

主要还是从算法所占用的「时间」和「空间」两个维度去考量。

时间维度:是指执行当前算法所消耗的时间,我们通常用「时间复杂度」来描述。

空间维度:是指执行当前算法需要占用多少内存空间,我们通常用「空间复杂度」来描述

时间复杂度

什么是时间复杂度

表示代码的运行时间,通过代码的执行次数来表示,大 O 时间复杂度表示法 实际上并不具体表示代码真正的执行时间,而是表示 代码执行时间随数据规模增长的变化趋势,所以也叫 渐进时间复杂度,简称 时间复杂度

如何计算

  • 直接运行,(受到硬件影响和数据规模比较大)
  • 大O符号表示法 ,即 T(n) = O(f(n)) n 表示数据规模的大小,f(n) 表示每行代码执行的次数总和。因为这是一个公式,所以用f(n) 来表示。公式中的 O,表示代码的执行时间 T(n) 与 f(n) 表达式成正比。

常见的时间复杂度:

  • 常数阶O(1)
const a = 1;
let b = 2;
  • 对数阶O(logN)
let i = 1;const n = 6;while (i < n) {  i = i * 2;}
  • 线性阶O(n)
for (let i = 0i <= n; i++) {    console.log('来过' + i +'常数');}
  • 线性对数阶O(nlogN)

for (let i = 0; i <= n; i++) {
    while (j < i) {
        j = j * 2;
    }
}
  • 平方阶O(n²)
for(x=1; i <= n; x++){
   for(i = 1; i <= n; i++) {
       j = i;
       j++;
    }
}
  • 立方阶O(n³)
for(x=1; i <= n; x++){
   for(i = 1; i <= n; i++) {
       j = i;
       j++;
       for(i = 1; i <= n; i++) {
       j = i;
       j++;
    	}
    }
}
  • K次方阶O(n^k)

上面从上至下依次的时间复杂度越来越大,执行的效率越来越低。

分析技巧

  • 多段代码取最大:有循环和多重循环的情况,取多重循环的复杂度
for(y=1; y <= m; y++){
     console.log(y)
  }
for(x=1; x <= n; x++){
   console.log(x)
   for(y=1; y <= m; y++){
     console.log(y)
  }
}

  • 嵌套代码求乘积:循环中的递归
for(x=1; x <= n; x++){
   console.log(x)
   for(y=1; y <= m; y++){
     console.log(y)
  }
}

  • 多个规模求和:分别有两个参数控制两个循环的次数,取二者的复杂度相加
let a=1;
let b=2
for(x=1; x <= n; x++){
   console.log(x)
}
for(y=1; y <= m; y++){
   console.log(y)
}

推导原则

  • 若运行时间是常数量级,则用常数 1 表示;
  • 只保留时间函数中最高阶项 ;
  • 若最高阶项存在,则省去最高阶项前的系数;

事件复杂度曲线

算法复杂度的分类

  • 最好情况: 在最理想的情况下,执行这段代码的时间复杂度。比如说刚才那段函数,在最理想的情况下,要查找的变量 x 正好是数组的第一个元素,这种情况下对应的时间复杂度就是最好情况时间复杂度。
  • 最坏情况时间复杂度:在最糟糕的情况下,执行这段代码的时间复杂度。比如说刚才那段函数,要查找的变量 x 正好是数组的第末个元素或者不在数组中存在 ,查找函数就会把数组都遍历一遍,这种情况下对应的时间复杂度就是最坏情况时间复杂度。
  • 平均时间复杂度:用代码在所有情况下执行的次数的加权平均值表示。也叫 加权平均时间复杂度 或者 期望时间复杂度 公式就是平均情况复杂度 = 累加每种遍历的元素个数 / 所有的情况数量
  • 均摊时间复杂度(:在代码执行的所有复杂度情况中绝大部分是低级别的复杂度,个别情况是高级别复杂度且发生具有时序关系时,可以将个别高级别复杂度均摊到低级别复杂度上。基本上均摊结果就等于低级别复杂度。

空间复杂度

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的一个量度(即除开原始序列大小的内存,在算法过程中用到的额外的存储空间),反映的对内存占用的趋势,而不是具体内存,用 来代替;

如何计算

  • 大O符号表示法 S(n)=O(f(n))

常见算法的空间复杂度

  • 常数阶O(1)
var a=1
var b=1
a++
b++
  • 线性阶O(n)
function print(n) {
 const newArr = []; 
 newArr.length = n; 
  for (let i = 0; i <n; ++i) {
    newArr[i] = i * i;
  }

  for (let j = n-1; j >= 0; --j) {
    console.log(newArr[i])
  }
}

  • 平方阶O(n²)
let index=0
var arr=[]
function print(n) {
 for(var i=0;i<n;i++){
   for(var i=0;i<n;i++){
   	arr[index++]=1
   }
 }

  
}

注意

时间复杂度和空间复杂度可以转化