通过js示例讲解时间复杂度与空间复杂度


Posted in Javascript onAugust 06, 2019

1. 博客背景

今天有同事在检查代码的时候,由于函数写的性能不是很好,被打回去重构了,细思极恐,今天和大家分享一篇用js讲解的时间复杂度和空间复杂度的博客

2. 复杂度的表示方式

之前有看过的,你可能会看到这么一串东西

T(n) = O(f(n)) 
S(n) = O(f(n))

这个叫做大O表示法,其中的T代表的是算法需要执行的总时间

S表示的算法需要的总空间

f(n)表示的是代码执行的总次数

举个例子

function go(n) { 
 var item = 0;   // 这里执行了一次
 for (var i = 0; i < n; i++) {  //这里执行了N次
  for (var j = 0; j < n; j++) {   //这里执行了n*n次
   item = item + i + j;   //这里执行了n*n次
  }
 }
 return item; //这里执行了一次
}

所以说上边这段代码是 1+n+n*n*2+1=2+n+2n²

也就是说 T(n) = O(f(2+n+2n²))

然后之前说了时间复杂度看的是一个代码执行的时间的趋势, 所以说在N,也就是规模比较大的时候,那些常量是起不到决定性的作用的,所以这个时候我们忽略这些常量,这里的例子是一个单段的代码,这里只看最大量级的循环就可以了

所以最后的这个代码的时间复杂度是T(n) = O(n²)

大家可以想想一下数据中平方的曲线图

3. 时间复杂度

3.1 时间复杂度的定义

首先什么是时间复杂度,时间复杂度这个定义如果在之前没有接触过的话,你可能会认为他代表的是一个代码执行的时间,其实不然,算法的时间复杂度就是说一个算法的执行时间根据数据规模增长的一个趋势,并不是说代码执行的具体时间

3.2 几种常见的时间复杂度

最简单的O(n)

for (var i = 0; i < n; i++) { 
sum += i; 
}

通俗易懂,这段代码的执行时间完全由N来控制,所以说T(n) = O(n)

当然还有个更简单的O(1)

function total(n) {

console.log(1)
}

无论怎么样,这段函数不受任何参数影响,代码走一遍就完事,这种的代码用T(n) = O(1) 表示

T(n) = O(n²)

上边的例子已经说了一个了两层循环的那种,在举一个时间复杂度多块代码的情况时间复杂度的计算方式

function go(i) {
 var sum = 0;
 for (var j = 0; j < i; j++) {
  sum += i;
 }
 return sum;
}
function main(n) {
 var res = 0;
 for (var i = 0; i < n; i++) {
  res = res + go(i); // 这里是重点
 }
}

在上边的代码种第二段代码里边调用了第一段代码,所以说在这个代码里边是

go:(1+n)

在main函数里边的时候是(1+n*go)=(1+n+n*n)

所以最后的时间复杂度是T(n) = O(n²)

3.3 多块代码的时间复杂度

上边距离说明的T(n) = O(n²) ,是一个函数在另一个函数里边被调用,这种情况是被把两个函数的时间复杂度相乘。

还有另外一种情况,就是说在一个函数里边有多块代码,但是并没有被相互调用,那么这种情况的时候,我们只需要取复杂度最大的代码块就可以了

比如说

function go(n) {

     for (var i = 0; i < n; i++) {
      for (var j = 0; j < n; j++) {
       console.log(1)
      }
     }


     for (var i = 0; i < n; i++) {
      console.log(2)
     }
    }

上边这块代码中,第一块代码有两层循环,通过上边的例子我们已经得知复杂度是

下边这块代码,是n

那么在这种情况的时候,当N接近无限大的时候N是对n²起不到决定性作用的,所以上边这块代码的时间复杂度就是取最大值的n²

3.4 对数阶和相加情况

var i = 1;
while (i <= n) {
    i = i * 10;
}

在这段代码中,可以看到while里边,作为判断条件的i被每次*10,那么所以说最后循环的次数并不是n次,而是说十分之一n次,所以说这个时候的时间复杂度是10i=n,
i=logn

所以得出结论就是时间复杂度是T(n)=O(logn)

然后还有一种情况就是通过改变的变量去增加循环次数的,同理是增加了时间复杂度

还有一些其他的情况比如时间复杂度相加

function go(m,n) {

 for (var i = 0; i < n; i++) {
  console.log(1)
 }

 for (var i = 0; i < m; i++) {
  console.log(2)
 }

}

请看上边这一段,这段代码里边一个函数里边有两个循环,但是形参有两个,我们现在无法得知n和m到底谁大谁小,所以说这个时候代码的时间复杂度是O(m+n)

4. 空间复杂度

4.1 空间复杂度的定义

上边说了那么一大堆的时间复杂度,相比各位已经比较了解了,就名字来看,时间复杂度看的是代码的执行时间的趋势,那么同理的,空间复杂度就是指的占用内存的趋势

4.2 常见的空间复杂度

空间复杂度没有时间复杂度那么复杂,常见的就那么几种

毕竟我感觉不会有人一直循环着各种花样的声明变量吧。。。

如果有,那么请打死。。。。

  • O(1)
let a = 1;
let b = 1;
let c = 1;
let d = 1;

很简单,O(1)

  • O(n)
let arr =Array(n)

看这句代码,代码中创建了一个n长度的数组,很明显数组的长度根据n来决定,所以说
O(n)

这里需要说明一下,这里没有用循环,是因为只要不是在循环里边不停的声明变量,只改变值的话是不会层架空间复杂度的

  • O(n²)
let arr=[]
for (var i = 0; i < n; i++) {
  arr[i]=i
  for (var j = 0; j < n; j++) {
    arr[i][j]=j
  }
}

怎么样,猛的一看这个代码是不是很刺激,我觉得如果有这种情况的话,一般都会被乱棍打死了。。。

复杂度的优化

再说优化之前我先盗一张图给大家看一下各个复杂度的曲线图,方便大家有一个直观的认识

通过js示例讲解时间复杂度与空间复杂度

举个比较简单的优化的例子

console.time('a')
function go(n) {
   var item = 0;
   for (var i = 1; i <= n; i++) {
    item += i;
   }
   return item;
}
console.timeEnd('a')

console.time('b')
function go2(n) {
 var item = n*(n+1)/2
 return item;
}
console.timeEnd('b')

go(1000)
go2(1000)

大家可以打印一下看一下

希望大家原谅我数学不好,记得之前看到过一个等差数列的例子,想不到其他的性能优化的例子

希望大家看完之后可以了解这些概念,有的时候这个东西真的很重要,找一个曲线比较高的例子

斐波那契,就是从第三项开始依次等于前两项的和

斐波那契定义

function Fibonacci(n) {
  if (n <= 1 ) {
    return n;
  } else {
    return Fibonacci(n - 1) + Fibonacci(n - 2);
  }
}

console.time('b')
Fibonacci(????)
console.timeEnd('b')

有兴趣的可以试试打印一下,看看时间,不过大概50次的时候你得浏览器就应该没有响应了,具体请往上看曲线图。。。。

以上是我对时间复杂度和空间复杂度的一些认识,有不足或者不对的地方,希望指出来

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
js绑定事件this指向发生改变的问题解决方法
Apr 23 Javascript
jQuery中校验时间格式的正则表达式小结
Sep 22 Javascript
Jquery动态替换div内容及动态展示的方法
Jan 23 Javascript
Google 地图叠加层实例讲解
Aug 06 Javascript
关于前后端json数据的发送与接收详解
Jul 30 Javascript
解决Angular.js中使用Swiper插件不能滑动的问题
Feb 26 Javascript
vue 使某个组件不被 keep-alive 缓存的方法
Sep 21 Javascript
element ui table 增加筛选的方法示例
Nov 02 Javascript
vue数据操作之点击事件实现num加减功能示例
Jan 19 Javascript
vue使用Proxy实现双向绑定的方法示例
Mar 20 Javascript
Vue CLI 3.x 自动部署项目至服务器的方法
Apr 02 Javascript
JointJS JavaScript流程图绘制框架解析
Aug 15 Javascript
Flutter 超实用简单菜单弹出框 PopupMenuButton功能
Aug 06 #Javascript
JS中如何轻松遍历对象属性的方式总结
Aug 06 #Javascript
VUE组件中的 Drawer 抽屉实现代码
Aug 06 #Javascript
浅入深出Vue之自动化路由
Aug 06 #Javascript
解决vue单页面修改样式无法覆盖问题
Aug 05 #Javascript
微信小程序3种位置API的使用方法详解
Aug 05 #Javascript
微信小程序 高德地图路线规划实现过程详解
Aug 05 #Javascript
You might like
php抓取https的内容的代码
2010/04/06 PHP
php+MySQL判断update语句是否执行成功的方法
2014/08/28 PHP
利用PHP获取网站访客的所在地位置
2017/01/18 PHP
php实现微信发红包功能
2018/07/13 PHP
PHP5.5新特性之yield理解与用法实例分析
2019/01/11 PHP
PHP的cookie与session原理及用法详解
2019/09/27 PHP
javascript当中的代码嗅探扩展原生对象和原型(prototype)
2013/01/11 Javascript
jQuery中$.click()无效问题分析
2015/01/29 Javascript
EasyUI中combobox默认值注意事项
2015/03/01 Javascript
jQuery实现仿Alipay支付宝首页全屏焦点图切换特效
2015/05/04 Javascript
jQuery实现背景弹性滚动的导航效果
2016/06/01 Javascript
node.js学习之base64编码解码
2016/10/21 Javascript
jQuery实现倒计时重新发送短信验证码功能示例
2017/01/12 Javascript
JS中Attr的用法详解
2017/10/09 Javascript
微信小程序解析富文本过程详解
2019/07/13 Javascript
vue实现将一个数组内的相同数据进行合并
2019/11/07 Javascript
JS面向对象编程基础篇(二) 封装操作实例详解
2020/03/03 Javascript
Vue-cli4 配置 element-ui 按需引入操作
2020/09/11 Javascript
python实现网站的模拟登录
2016/01/04 Python
深入解析Python设计模式编程中建造者模式的使用
2016/03/02 Python
Python3 虚拟开发环境搭建过程(图文详解)
2020/01/06 Python
Python sql注入 过滤字符串的非法字符实例
2020/04/03 Python
Python代码需要缩进吗
2020/07/01 Python
HTML5本地存储localStorage、sessionStorage基本用法、遍历操作、异常处理等
2014/05/08 HTML / CSS
HTML5实现移动端复制功能
2018/04/19 HTML / CSS
Timex手表官网:美国运动休闲手表品牌
2017/01/28 全球购物
美国在线宠物商店:Chewy
2019/01/12 全球购物
世界汽车零件:World Car Parts
2019/09/04 全球购物
竞职演讲稿范文
2014/01/11 职场文书
幼儿园五一活动方案
2014/02/07 职场文书
2014银行领导班子四风对照检查材料思想汇报
2014/09/25 职场文书
六查六看心得体会
2014/10/14 职场文书
煤矿安全生产工作总结
2015/08/13 职场文书
个人职业生涯规划之自我评估篇
2019/09/03 职场文书
SQL模糊查询报:ORA-00909:参数个数无效问题的解决
2021/06/21 Oracle
如何利用opencv判断两张图片是否相同详解
2021/07/07 Python