通过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 相关文章推荐
静态的动态续篇之来点XML
Aug 15 Javascript
javascript Excel操作知识点
Apr 24 Javascript
HTML5附件拖拽上传drop &amp; google.gears实现代码
Apr 28 Javascript
JS时间选择器 兼容IE6,7,8,9
Jun 26 Javascript
javascript判断机器是否联网的2种方法
Aug 09 Javascript
jQuery 绑定事件到动态创建的元素上的方法实例
Aug 18 Javascript
javascript学习笔记(六)数据类型和JSON格式
Oct 08 Javascript
JavaScript中innerHTML,innerText,outerHTML的用法及区别
Sep 01 Javascript
angularjs学习笔记之完整的项目结构
Sep 26 Javascript
通过Ajax使用FormData对象无刷新上传文件方法
Dec 08 Javascript
webpack4 SCSS提取和懒加载的示例
Sep 03 Javascript
微信小程序中的上拉、下拉菜单功能
Mar 13 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项目中比较通用的php自建函数的详解
2013/06/06 PHP
PHP Warning: Module 'modulename' already loaded in问题解决办法
2015/03/16 PHP
PHP中常用的魔术方法
2017/04/28 PHP
php 中self,this的区别和操作方法实例分析
2019/11/04 PHP
jQuery ajax在GBK编码下表单提交终极解决方案(非二次编码方法)
2010/10/20 Javascript
鼠标移动到图片名上,显示图片的简单实例
2013/07/14 Javascript
jQuery+ajax实现无刷新级联菜单示例
2015/05/21 Javascript
BooStrap对导航条的改造实践小结
2016/09/21 Javascript
webpack进阶——缓存与独立打包的用法
2017/08/02 Javascript
解决淘宝cnpm 安装后cnpm不是内部或外部命令的问题
2018/05/17 Javascript
jQuery中DOM操作原则实例分析
2019/08/01 jQuery
vue.js中ref及$refs的使用方法解析
2019/10/08 Javascript
用JS实现一个简单的打砖块游戏
2019/12/11 Javascript
继承行为在 ES5 与 ES6 中的区别详解
2019/12/24 Javascript
javascript 易错知识点实例小结
2020/04/25 Javascript
vue+elementui通用弹窗的实现(新增+编辑)
2021/01/07 Vue.js
[54:27]TNC vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
github配置使用指南
2014/11/18 Python
教你用Python脚本快速为iOS10生成图标和截屏
2016/09/22 Python
解决python写入mysql中datetime类型遇到的问题
2018/06/21 Python
在python中获取div的文本内容并和想定结果进行对比详解
2019/01/02 Python
关于pandas的离散化,面元划分详解
2019/11/22 Python
Python @property装饰器原理解析
2020/01/22 Python
python如何输出反斜杠
2020/06/18 Python
python 装饰器的基本使用
2021/01/13 Python
如何用用Python将地址标记在地图上
2021/02/07 Python
美国受欢迎的眼影品牌:BH Cosmetics
2016/10/25 全球购物
Audible英国:有声读物,30天免费试用
2019/10/16 全球购物
出纳员的岗位职责
2014/02/22 职场文书
2014五一国际劳动节活动总结范文
2014/04/14 职场文书
环保志愿者活动总结
2014/06/27 职场文书
2014年教师节红领巾广播稿
2014/09/10 职场文书
复制别人的成功真的会成功吗?
2019/10/17 职场文书
导游词之河北白洋淀
2020/01/15 职场文书
python中Tkinter 窗口之输入框和文本框的实现
2021/04/12 Python
Python学习之os包使用教程详解
2022/03/21 Python