算法复杂度分析

目录

一、计算资源

1、第十三届蓝桥杯 Python 组题目的时空限制汇总

2、Python 与 C/C++ 、Java 的限制对比

3、时间和空间限制

4、测量代码的运行时间

二、算法定义

1、计算复杂度

2、有哪些复杂度

三、算法评估 

1、分类

2、易解问题——难解问题:用多项式时间来区分

3、多项式函数与指数函数的增长对比

4、问题规模和可用算法(个人认为超级重要)

5、选择解题方法

6、例题举例

(1)暴力法(可拿部分的分)

(2)前缀和 (AC)


一、计算资源

  • 程序运行时需要的资源有两种
  • 时间:程序运行需要的时间
  • 空间:程序运行需要的存储空间
  • 资源是有限的

1、第十三届蓝桥杯 Python 组题目的时空限制汇总

2、Python 与 C/C++ 、Java 的限制对比

3、时间和空间限制

  • 程序必须在限定的时间和空间内运行结束。
  • 问题的“有效”解决,不仅在于能否得到正确答案,更重要的是能在合理的时间和空间内给出答案。 
  • 程序运行的时间:时间复杂度
  • 程序运行的空间:空间复杂度
  • O(n*m) 和 O(n*n*m):就是时间复杂度
  • 符号 O 表示复杂度, O(n*m) 可以粗略地理解为运行次数是 n*m
  • O(n*n*m) 比 O(n*m) 运行时间大 n 倍。

4、测量代码的运行时间

如何衡量代码运行的时间?在代码中打印运行时间,可以得到一个直观的认识。

下面代码只有一个 for 语句,代码对 k 进行累加,最后打印循环累加的运行时间。

(1)C++代码耗时:0.014

#include<bits/stdc++.h>
using namespace std;

int main() {
	int k=0,n=1e7;
	clock_t start,end;
	start=clock();
	for(int i=0;i<n;i++)
		k++;
	end=clock();
	cout<<(double)(end-start)/CLOCKS_PER_SEC;
	return 0;
}

(2)Python代码耗时:0.7999107837677002

from time import *
k,n=0,10000000
start=time()
for i in range(n):
    k+=1
end=time()
print(end-start)

Python 的 for 循环很耗时,比 C++ 的 for 循环慢约 77 倍!

  • 评测用的 OJ 服务器,性能可能比这个好一些,也可能差不多。
  • 对于C++题目,如果题目要求“时间限制: 1s”,那么内部的循环次数 n 应该在 1 亿次以内;
  • 对于同等规模的Python题目,时间限制一般是5 ~ 10s。

二、算法定义

算法(Algorithm) :对特定问题求解步骤的一种描述,是指令的有限序列。有5个特征:

(1) 输入:一个算法有零个或多个输入。

(2) 输出:一个算法有一个或多个输出。

(3) 有穷性:一个算法必须在执行有穷步之后结束,且每一步都在有穷时间内完成。

(4) 确定性:算法中的每一条指令必须有确切的含义,对于相同的输入只能得到相同的输出。

(5) 可行性:算法描述的操作可以通过已经实现的基本操作执行有限次来实现。

1、计算复杂度

  • 把 n 称为问题的数据规模,把程序的复杂度记为 O(n)。
  • 复杂度只是一个估计,不需要精确计算。
  • 例如在一个有 n 个数的无序数列中,查找某个数 a,可能第一个数就是 a,也可能最后一个数才是a。平均查找时间是 n/2 次,但是仍然把查找的时间复杂度记为 O(n)。
  • 在算法分析中,规模 n 前面的系数被认为是不重要的。

2、有哪些复杂度

如下图所示:

三、算法评估 

  • O(1) 计算时间是一个常数,和问题的规模 n 无关。
  • 用公式计算时,一次计算的复杂度就是 O(1),例如hash算法。
  • 在矩阵 A|M|N| 中查找 i 行 j 列的元素,只需要一次访问 A[i][j]。
  • O(logn) 计算时间是对数。
  • 通常是以 2 为底的对数,每一步计算后,问题的规模减小一倍。例如在一个长度为 n 的有序数列中查找某个数,用折半查找的方法,只需要 logn 次就能找到。
  • O(n) 计算时间随规模 n 线性增长。在很多情况下,这是算法能达到的最优复杂度,因为对输入的 n 个数,程序一般需要处理所有的数,即计算 n 次。例如查找一个无序数列中的某个数,可能需要检查所有的数。
  • O(nlogn) 算法可能达到的最优复杂度。
  • 快速排序算法是典型例子。
  • O(n^2) 一个两重循环的算法,复杂度是O(n^2)。
  • 例如冒泡排序,是典型的两重循环。
  • O(n^3)、 O(n^4)等等。
  • O(2n) 一般对应集合问题。
  • 例如一个集合中有 n 个数,要求输出它的所有子集。
  • O(n!) 在集合问题中,如果要求按顺序输出所有的子集,那么复杂度就是 O(n!)

1、分类

  • 把上面的复杂度分成两类:
  • 多项式复杂度,包括 O(1)、 O(n)、O(nlogn)、 O(nk)等,其中k是一个常数;
  • O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3)
  • 指数复杂度,包括O(2n)、O(n!)等。
  • O(2n) < O(n!) < O(n^n)

2、易解问题——难解问题:用多项式时间来区分

  • 一个算法是多项式复杂度:“高效”算法。
  • 指数复杂度:“低效”算法。
  • 多项式复杂度的算法,随着规模 n 的增加,可以通过堆叠硬件来实现,“砸钱”是行得通的;
  • 指数复杂度的算法,增加硬件也无济于事,其增长的速度超出了想象力。

3、多项式函数与指数函数的增长对比

4、问题规模和可用算法(个人认为超级重要)

5、选择解题方法

  • 竞赛所给的题目,一般都会有多种解法,它考核的是在限定时间和空间内解决问题。
  • 如果条件很宽松,那么可以在多种解法中选一个容易编程的简单算法,以节约这一题的编码时间,有利于队员做更多的题。简单算法一般指暴力法,不用复杂算法和复杂数据结构,虽然代码的效率低下,但是思路和编码非常简单。
  • 如果给定的时间和空间条件很苛刻,那么能选用的合适算法和数据结构就不多了。要得到100%的分数,需要用高效复杂的算法。如果不会复杂算法或时间来不及,可以用暴力法获得部分分数。

6、例题举例

求和  2022年第十三届蓝桥杯省赛,lanqiaoOJ 题号 2080

题目如下图:

(1)暴力法(可拿部分的分)

(2)前缀和 (AC)

以上, 算法复杂度分析

祝好!

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吕飞雨的头发不能秃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值