算法复杂度这一篇就够了

什么是算法的复杂度?

时间复杂度

时间复杂度指的就是这个程序需要计算的工作量

通常的说,这个算法的指令数越多,需要的时间就越长。一个算法中的语句执行次数称为语句频度,记为T(n)。时间复杂度记作:T(n)=O(f(n))。 这样用 O 来表示算法时间复杂度的方法我在下面会详细讲。n越来越大,算法执行时间的增长率和 f(n) 的增长率相同,称作算法的时间复杂度。f(n)是问题规模 n 的某个函数。
一般情况下 ,随着 n 的增大,T(n) 增长最慢的算法为最好的算法。

空间复杂度

空间复杂度指的就是这个算法运行时临时占用电脑储存空间的大小。

时间复杂度和空间复杂度并称为算法的复杂度。

O表示法

你可能听说过某某算法的复杂度是 O(n²),这就是 O表示法。

假设 a 是一个二维数组,O(n²) 的代码表示为:

for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
	cout<<a[i][j];
    }
}

每个算法在不同情况下的复杂度也不同,比如冒泡排序,它在最好的情况下比较一轮就可以完成排序,最坏情况下需要执行完两层循环才能完成排序。所以,我们把算法复杂度从最好情况、平均情况和最坏情况三个角度来评价。 而 O 表示法表示的是算法的最坏情况。

推导算法复杂度的方法

①:用1代替运行时间中的所有加法常数。

②: 在执行完 ① 后的运行次数函数中,只保留最高阶项。

③: 如果最高阶项存在且不是1,则去除与这个项相乘的常数。得到的结果就是大O阶。

常数阶

看这个代码

int a = 12,b = 18,num; //运行次数+1
num = a+b; //运行次数+1
cout<<num; //运行次数+1

很显然,这段代码用来计算 a+b。

我们来推导一下它的复杂度。

我们这里的运行时间 (也就是次数)是 f(n)=1+1+1=3,这就叫加法常数,我们把它变成1。这里没有最高阶项(最高阶项就是未知数的指数最高的项,因为1这一项没有未知数,算作加法常数),直接得到结果,算法复杂度为O(1)。我们称这样的复杂度为 O(1) 的算法为常数阶。

注意,只要 f(n) 是一个整数,不管它是 2,是 4 还是几,这个时间复杂度只能是 O(1),因为这些加法常数都要变成1。

平方阶

现在你知道了推导规则,你基本可以推导大部分程序的时间复杂度。

我再来举个复杂点的例子,就是一开始我举那个例子,我推一下它的复杂度。

for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
	cout<<a[i][j];
    }
}

首先,这是两层循环,外层循环执行 n 次,内层循环执行 n 次。

这里我要讲到一个乘法原则:嵌套循环的时间复杂度 = 内层循环执行次数 × 外层循环执行次数。

所以,这个循环嵌套的时间复杂度就是 O(n²)。

主定理

大家可能听说过递推算法,一些递推算法可以表示为 T(n) = aT(n/b)+f(n)。

其中 a>=1,b>1,f(n)是递推式以外的式子,可以是未知数和常数。

遇到这种情况,我们要计算出以b为底的a的对数。比如 b 的 x 次方等于 a,则称x是以b为底的a的对数。

我们还需要计算出 f(n) 的指数。需要注意1的指数是0,因为任何整数的0次方都等于1。还需要注意,sqrt(n)(也就是根号下n)的指数为1/2。

我们把 f(n)的指数和以b为底的a的对数比较,

如果他们相等,则这个算法的时间复杂度是 n的以b为底的a的对数次方×log f(n)。

如果 f(n)的指数大于以b为底的a的对数,则该算法复杂度为 O(f(n))

如果 f(n)的指数小于以b为底的a的对数,则该算法复杂度为 O(n的以b为底的a的对数次方)

完美结束

好的,这样就结束了呢,有错误请评论指正。

### 3.1 蓝桥杯 Python 必备知识与学习资源 蓝桥杯竞赛作为全国性的重要算法竞赛之一,对参赛者的编程能力和算法思维要求较高。对于使用 Python 语言参赛的选手,掌握以下知识和资源将有助于在竞赛中取得优异成绩。 #### 3.2 必备 Python 知识 1. **基础语法与数据结构**:包括列表、字典、集合、元组等基本数据结构的使用,以及函数、模块、异常处理等语法特性。掌握这些是解决算法题目的基础[^3]。 2. **字符串处理**:熟练使用字符串切片、字符串方法(如 `split`, `join`, `find`)等,处理输入输出问题,尤其是在处理复杂输入格式时尤为重要。 3. **文件读写与标准输入输出**:了解如何使用 `sys.stdin` 和 `sys.stdout` 提高输入输出效率,避免在大规模数据处理时出现超时问题。 4. **递归与分治**:理解递归的基本原理,能编写递归函数解决如阶乘、斐波那契数列、全排列等问题。 5. **常用算法模板**:例如排序算法(快速排序、归并排序)、查找算法(二分查找)、图算法(Dijkstra、Floyd、DFS、BFS)、动态规划、贪心算法等。例如,Dijkstra 算法可以使用 `heapq` 实现高效的最短路径计算[^2]: ```python import heapq def dijkstra(graph, start): dist = {node: float('inf') for node in graph} dist[start] = 0 heap = [(0, start)] while heap: d, u = heapq.heappop(heap) if d > dist[u]: continue for v, w in graph[u]: if dist[v] > d + w: dist[v] = d + w heapq.heappush(heap, (dist[v], v)) return dist ``` 6. **位运算与优化技巧**:位运算在某些题目中可以显著提升程序效率,例如 N 皇后问题中使用位运算代替传统回溯法,可以大幅减少运行时间[^3]。 7. **数学基础**:包括数论、组合数学、排列组合、概率论等,这些知识在解决某些数学建模类题目时非常关键。 #### 3.3 学习资源推荐 1. **在线刷题平台**:蓝桥云课题库、LeetCode、Codeforces、AtCoder 等平台提供大量算法题目,适合日常训练。LeetCode 还支持按标签筛选题目,便于专项练习[^2]。 2. **书籍推荐**:《算法竞赛入门经典(第2版)》是一本非常适合蓝桥杯备赛的书籍,内容涵盖广泛,适合初学者和进阶选手[^2]。 3. **调试工具与环境配置**:推荐使用 Visual Studio Code 配合 Code Runner 插件进行调试,能快速运行和调试 Python 代码,提高编码效率[^2]。 4. **GitHub 资源仓库**:可以在 GitHub 上找到蓝桥杯的题解仓库,如 `https://github.com/lanqiao-python-solutions`,这些仓库通常包含历年真题的详细解析和代码实现[^3]。 5. **官方资源与社区支持**:蓝桥杯官方网站和相关论坛提供历年真题、比赛规则、评分标准等信息,有助于了解考试趋势和命题风格[^4]。 #### 3.4 竞赛备赛策略 1. **阶段训练计划**: - **基础阶段**(2周):掌握 Python 基础语法和常用数据结构。 - **提高阶段**(4周):重点训练动态规划、搜索算法、图论等中高级算法。 - **冲刺阶段**(2周):模拟真题训练,熟悉考试节奏,优化代码效率。 2. **常见失分点分析**: - **边界条件处理错误**(占错误率的 32%):例如数组越界、空输入等情况。 - **大数运算溢出**(28%):Python 的整数精度没有限制,但仍需注意逻辑错误。 - **递归深度超限**(25%):Python 默认递归深度有限,需手动设置 `sys.setrecursionlimit()`。 - **空间复杂度超标**(19%):避免不必要的数据结构嵌套,注意内存使用情况。 3. **得分关键点**: - **填空题**:善用 Python 的大整数计算优势,直接写出表达式即可。 - **编程题**:优先保证部分样例通过,采取“部分分策略”。 - **难题突破**:先写出暴力解法,再逐步优化,确保至少能通过部分测试点。 4. **实战技巧**: - **代码简洁性**:Python 的列表推导式、生成器、内置函数等可以帮助写出更简洁高效的代码。 - **时间复杂度分析**:学会估算算法的时间复杂度,避免超时。 - **调试技巧**:合理使用 `print()` 和断点调试,快速定位逻辑错误。 ---
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值