开篇 | 算法-从菜鸟开始

简介: 本文是《算法-从菜鸟开始》系列文章的开篇,欢迎收藏、留言、点赞。

一、何为算法


在计算机程序中通过某种计算方式(如利用某种数据结构、使用某种思维模式)以达到程序计算的目的,此种方式即是算法


二、算法的意义


如同人生的意义一样,都是在有限的时间、空间内争取最优解!


消耗最少的时间、空间资源,获取最符合预期的效果!


三、如何判定算法最优解


在算法的世界里,存在两个非常重要的概念:时间复杂度空间复杂度


时间复杂度: 用于描述一个算法整个执行过程中所消耗的时间。


空间复杂度 用于描述一个算法在执行过程中所占用的存储空间。


一般来说,一个算法的时间复杂度越低,空间复杂度越低,则该算法就是最优的一种解。


但并不是说,时间或者空间某一个维度的值极低视为一个最优解,而是趋近于某种”平衡“状态下,时间复杂度和空间复杂度都可以接受,视为最优解。


四、时间复杂度


时间复杂度全称为渐进时间复杂度,并不是用来描述该算法的实现实际的执行时间,而是一种描述算法执行时间与数据规模之间的增长关系。


使用大OOO表示法来描述时间复杂度,如O(1)O(1)O(1)O(n)O(n)O(n)O(n2)O(n^2)O(n2)O(logn)O(logn)O(logn)O(log2n)O(log_2n)O(log2n)


时间复杂度 描述
O(1)O(1)O(1) 常数阶,无论数据规模大小,其复杂度都是一样的
O(n)O(n)O(n) 线性阶,随着数据规模变大,其复杂度成线性递增
O(n2)O(n^2)O(n2) 平方阶,或者可以描述为指数阶, 如O(n2)O(n^2)O(n2)O(nk)O(n^k)O(nk)
O(logn)O(logn)O(logn) 对数阶, 是对指数阶的逆运算,如O(logn)O(logn)O(logn)O(log2n)O(log_2n)O(log2n)O(log3n)O(log_3n)O(log3n)


  1. O(1)O(1)O(1) 常数阶:


function printN (n) {
  const a = 1;
  const b = 2;
  const c = 3;
  console.log(a + b + c);
}


我们认为无论在函数体中有多少个变量,有多少行,如果没有循环、递归,我们都认为该程序在执行时的时间复杂度都是O(1)O(1)O(1)


即使有循环、递归,也要看是否和nnn有关系


function printN (n) {
  // 注意这里的是1000,固定值
  for (let i = 0; i < 1000; i++) {
    console.log(i)
  }
}


在这个例子中,不管nnn如何变化,执行时间都是固定的,所以该算法的时间复杂度仍旧是O(1)O(1)O(1),常数阶。


  1. O(n)O(n)O(n) 线性阶:


function printN (n) {
  for (let i = 0; i < n; i++) {
    console.log(i);
  }
}
printN(1);
printN(6);
printN(10);


随着nnn的增大,算法的执行时间线性增长。


  1. O(n2)O(n^2)O(n2) 平方阶:


function printN (n) {
  for (let a = 0; a < n; a++) {
    for (let b = 0; b < n; b++) {
      console.log(a + b);
    }
  }
}


在该函数执行时,两层循环,消耗时间为n∗n=n2n*n = n^2nn=n2,如果是嵌套3层循环,则为n3n^3n3,如果是嵌套k层循环,则为nkn^knk


  1. O(logn)O(logn)O(logn) 对数阶:


function prinitN (n) {
  const i = 1;
  while (i <= n) {
    console.log(n);
    i *= 2;
  }
}
printN(8);


在该函数中实际打印的是 ”1 2 4 8" 执行了4次,i的值是持续*2翻倍的。如果使用x表示执行的次数,xxx000开始,则2x=n2^x = n2x=nx=log2nx = log_2nx=log2nxxx是以222为底,nnn的对数。


如果此处是 i *= 3,则x=log3nx = log_3nx=log3nxxx是以333为底,nnn的对数。


常量忽略原则:


在算法的复杂度中,如果是常量,是可以被忽略不计的。所以就是 O(log2n)=O(log3n)=O(logn)O(log_2n) = O(log_3n) = O(logn)

O(log2n)=O(log3n)=O(logn)。 所以忽略底数,所有对数阶的复杂度都可以记为O(logn)O(logn)O(logn)


由以上一系列知识,可得如下时间复杂度计算规则。


时间复杂度计算规则


  1. 在一个算法中,存在多个复杂度,如O(n)O(n)O(n)O(n2)O(n^2)O(n2),存在明确的大小关系,取最大时间复杂度。如果不能明确的确定大小关系,则取二者的复杂度之和;


O(n2)>O(n)O(n^2) > O(n)O(n2)>O(n),则该算法的时间复杂度取为O(n2)O(n^2)O(n2)


如存在O(m)O(m)O(m)O(n)O(n)O(n)O(k)O(k)O(k)时间复杂度,不能明确mmmnnnkkk的大小,则该算法的时间复杂度为 O(m)+O(n)+O(k)O(m) + O(n) + O(k)O(m)+O(n)+O(k)


  1. 常数阶复杂度在与其他阶复杂度同时存在时,可以忽略不计;


  1. 多层嵌套的时间复杂度为:内外复杂度的乘积;


// 此算法的时间复杂度是多少呢?
function printN (m, n) {
  for (let i = 0; i < m; i++) {
    for (let j = 0; j < n; j++) {
      console.log(m, n)
    } 
  }
}


此函数算法的时间复杂度为 O(m)∗O(n)O(m) * O(n)O(m)O(n)


五、空间复杂度


空间复杂度全称为渐进空间复杂度,同时间复杂度一样,不是描述算法在执行时实际占用的存储空间,而是一种描述算法占用的存储空间与数据规模之间的增长关系。

空间复杂度也是使用大OOO来表示的。


空间复杂度 描述
O(1)O(1)O(1) 常数阶,无论数据规模大小,其复杂度都是一样的
O(n)O(n)O(n) 线性阶,随着数据规模变大,其复杂度成线性递增
O(n2)O(n^2)O(n2) 平方阶,或者可以描述为指数阶, 如O(n2)O(n^2)O(n2)O(nk)O(n^k)O(nk)

空间复杂度的计算规则也是同时间复杂度是一样的。


  1. O(1)O(1)O(1) 常数阶:


function printN (n) {
  const a = 10;
  const b = 10;
  const c = 20;
  console.log(a + b + c);
}


空间复杂度为常数阶,只是声明了几个变量,与nnn的值变化并没有关系,复杂度为O(1)O(1)O(1)


  1. O(n)O(n)O(n) 线性阶:


function saveArr (n) {
  const arr = [];
  for (let i = 0; i < n; i++) {
    arr.push(i);
  }
}


变量arr的存储空间长度与nnn是成线性关系增长的


  1. O(n2)O(n^2)O(n2) 平方阶:


function saveArr (n) {
  const arr = [];
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      arr.push(i, j);        
    }
 }
}


变量arr此时为二维数组,空间复杂度为O(n2)O(n^2)O(n2)


六、总结


在今天的文章中,我们初识算法,了解了算法的意义、如何求算法的最优解等。 同时我们掌握了两个非常重要的概念:时间复杂度空间复杂度,并且知道了如何计算时间复杂度和空间复杂度。


今天是《算法-从菜鸟开始》的开篇,接下来胡哥会和大家一起,针对LeetCode上的经典算法问题,由浅入深,一一深入了解。


算法-从菜鸟开始,而无止境。与君共勉!


相关文章
|
关系型数据库 MySQL 索引
17. MYSQL超大分页怎么处理 ?
`MYSQL`超大分页效率低,因为实际是获取`offset+N`行再丢弃前`offset`行。解决方法:先通过索引快速定位所需ID,然后进行关联查询获取数据,以提高性能。
206 0
|
消息中间件 机器学习/深度学习 存储
字节跳动大数据开发面试题-附答案 (一)
此面试题来自牛客网友分享的字节跳动应届一面,面试时长一小时。 网友情况:985 本硕。
2195 0
字节跳动大数据开发面试题-附答案 (一)
|
JavaScript 关系型数据库 应用服务中间件
Centos7安装wiki.js
Centos7安装wiki.js
1058 0
|
8月前
|
人工智能 API 语音技术
EmotiVoice:网易开源AI语音合成黑科技,2000+音色情感可控
EmotiVoice是网易有道开源的多语言语音合成系统,支持中英文2000多种音色,通过提示词控制情感输出,提供Web界面和API接口,具备语音克隆等先进功能。
927 43
EmotiVoice:网易开源AI语音合成黑科技,2000+音色情感可控
|
10月前
|
SQL 存储 Oracle
【YashanDB观点】论Oracle兼容性,我们需要做什么
Oracle兼容性是目前国产数据库的关键任务之一,其直接影响到商业迁移的成本和竞争力。
192 8
|
SQL 存储 自然语言处理
Sharding-JDBC 的基本用法和基本原理
Sharding-JDBC 的基本用法和基本原理
|
JSON 移动开发 前端开发
情人节福利,撩妹神器恋爱话术库它来了~
情人节福利,撩妹神器恋爱话术库它来了~
928 0
情人节福利,撩妹神器恋爱话术库它来了~
|
Web App开发 Dart JavaScript
无影Flutter for Web技术预研
## 介绍 [Flutter](https://flutter.dev/)是Google推出并[开源](https://github.com/flutter)的跨平台开发框架,它采用Skia渲染并兼容了Android、iOS、Mac、Windows、Linux及Web,Flutter在2.0版本正式发布了对Web的支持 ![](https://ata2-img.oss-cn-zhangjiak
1254 0
无影Flutter for Web技术预研
|
存储 SQL Java
Java面向对象程序设计期末题库(判断题)
Java面向对象程序设计期末题库(判断题)
2795 1
|
存储 Kubernetes 安全
K8S与Vault集成,进行Secret管理
K8S与Vault集成,进行Secret管理
K8S与Vault集成,进行Secret管理