判断时间复杂度和空间复杂度

本文介绍了时间复杂度和空间复杂度的基本概念及其计算方法。通过实例详细解释了如何确定算法的时间复杂度,并讨论了递归算法的空间复杂度计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

之前听别人说时间复杂度是多少多少,一脸蒙蔽,这么高大上的东西我怎么不会判断呢。这里特别强调一下,学习是我的初衷,写博客是为了巩固,这篇博客参考了下面这篇博客,我觉得写的很好,我这里也再总结以下。
https://blog.youkuaiyun.com/halotrriger/article/details/78994122

介绍

https://baike.baidu.com/item/%E6%97%B6%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6/1894057?fr=aladdin 时间复杂度-百度百科
https://baike.baidu.com/item/%E7%A9%BA%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6/9664257?fr=aladdin 空间复杂度-百度百科

时间复杂度的计算

计算时间复杂度主要是要找到各个语句执行的次数,再找出相同的数量级。
时间复杂度的定义:T(n) = O(f(n))。
其中,f(n)是T(n)的同数量级函数。同数量级函数就是说,当n趋近于无穷大时候,T(n)/f(n)极限不等于0。
下面举个栗子:

for(i=1; i<=n; ++i)
{
    for(j=1; j<=n; ++j)
    {
        c[i][j] = 0;//该步骤属于基本操作执行次数:n的平方次
        for(k=1; k<=n; ++k)
            c[i][j] += a[i][k] * b[k][j];//该步骤属于基本操作执行次数:n的三次方次
    }
}

这个算法,T(n) = n^3+n^2,由于当f(n)=n^3时,T(n)/f(n) 当n趋于无穷时,不等于0,故f(n)是T(n)的同数量级函数。时间复杂度为O(f(n)) = O(n^3)。
常见数量级有:
1,log2n,n,nlog2n,n^2,n^3,,n!,2^n

空间复杂度

类似于时间复杂度
1.递归算法的空间复杂度=递归深度N*每次递归所要的辅助空间
2.对于单线程来说,递归有运行时堆栈,求的是递归最深的那一次压栈所耗费的空间的个数,因为递归最深的那一次所耗费的空间足以容纳它所有递归过程。

在 Python 中,**时间复杂度****空间复杂度**是衡量算法效率的核心指标,分别描述操作执行时间与内存占用随输入规模的增长趋势。以下是针对 `list.pop()` 及相关操作的详细分析: --- ### **1. 时间复杂度(Time Complexity)** 时间复杂度表示算法执行时间与输入规模 `n` 的关系,通常用大 O 符号(O(n))表示。 #### **(1) `list.pop()` 的时间复杂度** - **`pop()`(默认移除末尾元素)**: **O(1)** - 只需修改列表的末尾指针,无需移动其他元素。 - **示例**: ```python lst = [1, 2, 3, 4] lst.pop() # 直接移除 4,时间复杂度 O(1) ``` - **`pop(index)`(移除指定索引元素)**: **O(n)** - 需移动 `index` 之后的所有元素(向索引减小的方向填充)。 - **示例**: ```python lst = [1, 2, 3, 4] lst.pop(0) # 移除 1 后,需将 2,3,4 向前移动,时间复杂度 O(n) ``` #### **(2) 其他常见操作的时间复杂度** | 操作 | 时间复杂度 | 说明 | |---------------------|------------|-----------------------------| | `list.append(x)` | O(1) | 平均情况下(动态扩容摊还分析) | | `list.insert(i, x)` | O(n) | 需移动插入点后的所有元素 | | `list.remove(x)` | O(n) | 需遍历列表找到第一个 `x`,再移动元素 | | `list[index]` | O(1) | 直接通过索引访问 | | `x in list` | O(n) | 需遍历列表检查是否存在 `x` | #### **(3) 为什么 `pop(0)` 比 `pop()` 慢?** - `pop(0)` 需要移动所有剩余元素(如 `[1,2,3] → [2,3]` 需移动 2 3)。 - `pop()` 仅修改末尾指针,无数据移动。 --- ### **2. 空间复杂度(Space Complexity)** 空间复杂度表示算法执行过程中额外占用的内存空间与输入规模 `n` 的关系。 #### **(1) `list.pop()` 的空间复杂度** - **O(1)** - `pop()` 操作本身不需要额外分配内存(仅修改原列表的指针或数据)。 - **例外**:若列表因动态扩容导致内存重新分配(如 `append` 触发扩容),但 `pop` 通常不会触发。 #### **(2) 常见操作的空间复杂度** | 操作 | 空间复杂度 | 说明 | |---------------------|------------|-----------------------------| | `list.append(x)` | O(1) | 平均情况下(动态扩容摊还分析) | | `list.copy()` | O(n) | 需创建新列表存储副本 | | 列表推导式 `[x for x in lst]` | O(n) | 生成新列表 | | 排序 `lst.sort()` | O(1) | 原地排序(Timsort 算法) | #### **(3) 动态扩容对空间复杂度的影响** - Python 列表在 `append` 时会预分配额外空间(避免频繁扩容),但 `pop` 通常不会释放内存(除非显式调用 `lst.clear()` 或重新赋值)。 - **示例**: ```python lst = [0] * 1000 # 分配 1000 个元素的内存 lst.pop() # 移除一个元素,但内存仍保留 1000 个元素的空间 ``` --- ### **3. 复杂度对比示例** #### **(1) 遍历列表并 `pop(0)`(低效)** ```python lst = [1, 2, 3, 4] while lst: lst.pop(0) # 每次 O(n),总时间复杂度 O(n²) ``` - **时间复杂度**:O(n²)(n 次操作,每次 O(n))。 - **空间复杂度**:O(1)(无额外空间)。 #### **(2) 用 `deque` 优化(高效)** ```python from collections import deque dq = deque([1, 2, 3, 4]) while dq: dq.popleft() # O(1) 操作 ``` - **时间复杂度**:O(n)(n 次 O(1) 操作)。 - **空间复杂度**:O(n)(需存储 `deque`)。 --- ### **4. 实际应用中的优化建议** 1. **避免频繁 `pop(0)`**: 改用 `collections.deque` 的 `popleft()`(O(1))。 ```python from collections import deque dq = deque([1, 2, 3]) dq.popleft() # 高效移除队首 ``` 2. **批量删除元素时反向遍历**: 避免正向遍历 `pop` 导致的索引错乱。 ```python lst = [1, 2, 3, 4, 5] for i in range(len(lst)-1, -1, -1): if lst[i] % 2 == 0: lst.pop(i) # 安全删除 ``` 3. **预分配列表空间**: 若已知大致规模,用 `[None] * n` 预分配内存,减少动态扩容开销。 ```python n = 1000 lst = [None] * n # 一次性分配 ``` --- ### **5. 复杂度分析工具** - **时间复杂度**:通过操作次数随 `n` 的增长趋势判断(如嵌套循环通常是 O(n²))。 - **空间复杂度**:统计算法执行过程中额外使用的变量或数据结构大小。 --- ### **
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值