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

时间复杂度

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

例子:
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) (递归存在时,计算机会专门分配一块空间,来存储"方法调用栈",当进入更深一层函数时,会进行入栈操作,执行完会进行出栈操作, 因此递归所需要的内存空间跟递归的深度成正比。)
  • 如果是在循环体中申请的数组等,可能就需要取嵌套的乘积来作为空间复杂度,这种就需要具体的进一步分析。
相关推荐
闭着眼睛学算法3 小时前
【双机位A卷】华为OD笔试之【模拟】双机位A-新学校选址【Py/Java/C++/C/JS/Go六种语言】【欧弟算法】全网注释最详细分类最全的华子OD真题题解
java·c语言·javascript·c++·python·算法·华为od
玉夏3 小时前
【每日算法C#】爬楼梯问题 LeetCode
算法·leetcode·c#
学好statistics和DS3 小时前
【CV】泊松图像融合
算法·计算机视觉
贝塔实验室3 小时前
QPSK信号载波同步技术---极性Costas 法载波同步
计算机网络·算法·网络安全·数学建模·信息与通信·信号处理·傅立叶分析
前端小刘哥4 小时前
视频直播点播平台EasyDSS视频直播功能的技术实现与应用场景解析
算法
前端小刘哥4 小时前
企业运营效率瓶颈?新版视频直播点播平台EasyDSS用视频能力破局!
算法
曦樂~4 小时前
一些可用于排序的函数(2542. 最大子序列的分数)
算法
CAU界编程小白4 小时前
数据结构系列之堆
数据结构·c
colus_SEU5 小时前
【编译原理笔记】2.1 Programming Language Basics
c++·算法·编译原理
人工智能培训5 小时前
大模型-去噪扩散概率模型(DDPM)采样算法详解
算法