对时间复杂度和空间复杂度的理解

时间复杂度

在算法中,所谓的时间复杂度可以简单的理解成为算法的运行时间。接下来我们可以简单的去看一下时间复杂度是怎么计算的

例子:
javascript 复制代码
function print1() {
  console.log('打印')
}
// 函数内代码只执行了1次

function print2(n) {
  for (let i = 0; i < n; i++) {
    console.log('打印')
  }
}

第一个 print1 很明显的看出来只执行了1次

第二个函数:对于print2 我们可以先假设 **n = 2

**

回到 n 这个数上,我们再计算一下执行了几次

可以得出结果就是 一共执行了 3n + 2次

结论

通常一段代码的总执行次数,我们会用T(n)来表示, 而如果n的数据比较大时,T(n)来表达就不是很合适。在算法中,我们通常会用T(n)的简化估算值 来计算代码的运行速度,而这个估算值就被称为时间复杂度。

T(n) --> 时间复杂度
  • print1 = T(n) = 1 --> 对于T(n)是个常数时,可以直接将其估算成 1 --> O(1)
  • print2 = T(n) = 3n + 2 --> 如果n足够大的时候,可以理解成忽略其常数和n前面的系数,也就n --> O(n)
  • 补充: T(n) = 4n^8 + 10n^7 + 2 -->同样的道理,n足够大时,取n的次方最大作为复杂度--> O(n^8)

常见的例子
例子1:
js 复制代码
function print1() {
  console.log('打印1') // 打印了一次
  console.log('打印2') // 打印了一次
  console.log('打印3') // 打印了一次
  console.log('打印4') // 打印了一次
  console.log('打印5') // 打印了一次
}
// 复杂度 O(1)
例子2:
js 复制代码
function print2(n) {
  for (let i = 0; i < n; i++) {
    console.log('打印') // 打印了一次
  }
}
// 复杂度 O(n)

可以简单总结出来:代码存在多少层循环,时间复杂度就是多少。

例子3:
js 复制代码
function print3(n) {
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      console.log('打印') // 打印了一次
    }
  }
  for (let k = 0; k < n; k++) {
    console.log('打印') // 打印了一次
  }
}
// 当 i = 0,内部会执行 n + 1 次, i = 1, 持续 2n + 2,依次类推,应该会执行个 n*n + n = n^2+n 次。
// 复杂度为O(n^2)
例子4:
js 复制代码
function print4(n) {
  if (n > 100) {
    for (let i = 0; i < n; i++) {
      for (let j = 0; j < n; j++) {
        console.log('打印') // 打印了一次
      }
    }
  } else {
    for (let i = 0; i < n; i++) {
      console.log('打印') // 打印了一次
    }
  }
  
}
// 如果是存在判断条件,则还是以最长运行时间最为最终结果
// 复杂度为O(n^2)
例子5:
js 复制代码
function print5(n) {
  for (let i = 0; i < n; i++) {
    for (let j = i; j < n; j++) {
      console.log('打印') // 打印了一次
    }
  }
}
// i = 0 -> n
// i = 1 -> n - 1
// ...
// i = n - i -> 1
// T(n) = n + (n - 1) + (n - 2) + .... + 2 + 1 = n(n + 1) / 2 = 1/2 * n^2 + 1/2*n
// 复杂度为O(n^2)
例子6:
js 复制代码
function print6(n) {
  for (let i = 0; i < n; i * 2) {
    console.log('打印') // 打印了一次
  }
}
// 假设 n = 8
// T(n) = 3 --> 2^3 = 8 --> log(2)(8) = 3(指数和对数的转换)
// 复杂度可以简单表示成 O(logn) -->(当n足够大时,可以忽略其底数,只保留其真数和对数)

可以补充一下简单的数学知识

两者可以相互转换,转换公式为a^x=N <=> log(a)(N) = x

例子7:
js 复制代码
function print(n) {
  for(let j = 0; j < n; j++) {
    for (let i = 0; i < n; i * 2) {
      console.log('打印') // 打印了一次
    }
  }
}
// 由例子6可以简单得出:
// 复杂度为O(nlog(n))

空间复杂度

空间复杂度可以简单理解成一个算法在运行过程中占用存储空间大小 的度量。通常来说,计算一个算法的空间复杂度公式为:S(n) = O(fn(n)) 其中n 为问题的规模,fn为算法所占用空间大小的函数

例子:
js 复制代码
function print(n) {
  let a = []
  const b = 1 // 是个常量 -> 1
  for(let i = 0; i < n; i++) {
    a.push(i); // a的大小随的n变而变大
  }
}
// 我们可以简单的估量程序所占用 a占用了n个空间,b暂用了一个,一共为n+1 --> O(n)
常见的几种复杂度:
  • 如果申请的是有限个数(常量)的变量(变量空间 ),空间复杂度为 O(1)
  • 如果申请的是一维数组,队列或者链表(线性空间 )等,那么空间复杂度为 O(n)
  • 如果申请的是二维数组(二维空间 ),那么空间复杂度为 O(n²)
  • 如存在递归则比较特殊(递归空间 ),空间复杂度为O(n) (递归存在时,计算机会专门分配一块空间,来存储"方法调用栈",当进入更深一层函数时,会进行入栈操作,执行完会进行出栈操作, 因此递归所需要的内存空间跟递归的深度成正比。)
  • 如果是在循环体中申请的数组等,可能就需要取嵌套的乘积来作为空间复杂度,这种就需要具体的进一步分析。
相关推荐
秋夫人16 分钟前
B+树(B+TREE)索引
数据结构·算法
代码雕刻家1 小时前
数据结构-3.1.栈的基本概念
c语言·开发语言·数据结构
梦想科研社1 小时前
【无人机设计与控制】四旋翼无人机俯仰姿态保持模糊PID控制(带说明报告)
开发语言·算法·数学建模·matlab·无人机
Milo_K1 小时前
今日 leetCode 15.三数之和
算法·leetcode
Darling_001 小时前
LeetCode_sql_day28(1767.寻找没有被执行的任务对)
sql·算法·leetcode
AlexMercer10121 小时前
【C++】二、数据类型 (同C)
c语言·开发语言·数据结构·c++·笔记·算法
Greyplayground1 小时前
【算法基础实验】图论-BellmanFord最短路径
算法·图论·最短路径
蓑 羽1 小时前
力扣438 找到字符串中所有字母异位词 Java版本
java·算法·leetcode
源代码:趴菜1 小时前
LeetCode63:不同路径II
算法·leetcode·职场和发展
儿创社ErChaungClub1 小时前
解锁编程新境界:GitHub Copilot 让效率翻倍
人工智能·算法