当前位置: 首页 > news >正文

【数据结构】时间复杂度与空间复杂度

算法效率

1.解释:用来衡量一个算法的好坏

2.斐波那契数列:有几个实现代码,其中一个递归看着很简单,但是这就一定是一个有效率的代码。这应该不是的。

3.对于算法效率,我们引出一个名词:算法的复杂度,我们运行程序是花费时间与空间(内存)的

,因此我们衡量一个算法的好坏,就看它用的时间复杂度与空间复杂度。

4.时间复杂度主要是衡量这个算法的运行的快慢。

5.时间复杂度主要是衡量这个算法运行的所需额外空间。

时间复杂度(函数)

1.算法的时间复杂度的计算,我们最直接的方法就是上机测试这个算法,但我们想要计算它便要看他其中的语句的运行次数(与算法花费时间成正比)。

2. O的渐进表示法:从渐进中,我们就可以看出他一个大概的计算的方法。比如我们高中所学的放缩里就有这个概念:就是将不影响结果的因数给舍去掉。在大O的渐进表示法里,O(2n)(指数阶)> O(n3)(立方阶)> O(n2)(平方阶)> O(nlogn)(nlogn 阶)> O(n)(线性阶)> O(logn)(对数阶)> O(1)(常数阶)。

3.最好,最坏,平均(情况),我们该选谁:最坏。

空间复杂度

1.是指算法在运行中临时占用存储空间的大小的量度。也是用大O渐进表示法。对于空间复杂度不是计算程序占了多少bytes,而是计算变量的个数。

2.注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定,也就是说空间复杂度主要看程序运行中临时 “额外要” 的空间.

案例

时间复杂度:

1.

// 计算Func2的时间复杂度?
void Func2(int N)
{int count = 0;for (int k = 0; k < 2 * N ; ++ k){++count;}int M = 10;while (M--){++count;}printf("%d\n", count);
}

for循环里O(N) ,while循环里O(1)取”大“的

所以时间复杂度:O(N)

2.

// 计算Func3的时间复杂度?
void Func3(int N, int M)
{int count = 0;for (int k = 0; k < M; ++ k){++count;}for (int k = 0; k < N; ++ k){++count;}printf("%d\n", count);
}

 第一个for循环里是O(M) 第二个for O(N) 两个都是同一级别的

所以时间复杂度是O(N+M)

3.

// 计算Func4的时间复杂度?
void Func4(int N)
{int count = 0;for (int k = 0; k < 100; ++ k){++count;}printf("%d\n", count);
}

for循环里O(1)

所以时间复杂度是O(1) 

4.

// 计算BubbleSort的时间复杂度?
void BubbleSort(int* a, int n)
{assert(a);for (size_t end = n; end > 0; --end){int exchange = 0;for (size_t i = 1; i < end; ++i){if (a[i-1] > a[i]){Swap(&a[i-1], &a[i]);exchange = 1;}}if (exchange == 0)break;}
}

 最坏:逆序  时间复杂度是O(N**2)

最好:有序 ,时间复杂度是O(N)

所以时间复杂度我们取最坏的

5.

// 计算BinarySearch的时间复杂度?
int BinarySearch(int* a, int n, int x)
{assert(a);int begin = 0;int end = n-1;while (begin < end){int mid = begin + ((end-begin)>>1);if (a[mid] < x)begin = mid+1;else if (a[mid] > x)end = mid;elsereturn mid;}return -1;
}

  1. 每次循环,查找范围从 [begin, end] 缩小为 [begin, mid] 或 [mid + 1, end],数据规模约折半。
  2. 最多经过 log2​n 次(以 2 为底 n 的对数)缩小操作,就能确定结果,故时间复杂度是 O(logn) 。

6.

// 计算阶乘递归Fac的时间复杂度?
long long Fac(size_t N)
{if(0 == N)return 1;return Fac(N-1)*N;
}

时间复杂度O(N) 。递归调用 Fac(N - 1) ,从 N 依次递归到 0 ,共进行 N 次递归调用,每次调用执行常数时间操作,所以时间复杂度是线性的,为 O(N) 。

7.

// 计算斐波那契递归Fib的时间复杂度?
long long Fib(size_t N)
{if(N < 3)return 1;return Fib(N-1) + Fib(N-2);
}

时间复杂度O(2^N) 。递归计算 Fib(N) 时,会产生大量重复递归调用(比如计算 Fib(N) 要调用 Fib(N - 1) 和 Fib(N - 2) ,这两个又会各自调用更小的分支 ),递归树的节点数约为 2^N 量级,所以时间复杂度是指数级的 O(2^N) 。

空间复杂度:

1.

// 计算BubbleSort的空间复杂度?
void BubbleSort(int* a, int n)
{assert(a);for (size_t end = n; end > 0; --end){int exchange = 0;for (size_t i = 1; i < end; ++i){if (a[i - 1] > a[i]){Swap(&a[i - 1], &a[i]);exchange = 1;}}if (exchange == 0)break;}
}

输入的数组 a 是待排序数据,属于输入本身占用的空间,不计入额外空间。

额外定义的变量有 endexchangei 等,这些变量占用的空间是固定的,不随输入数据规模 n 的变化而变化 。

所以,冒泡排序(Bubble Sort)的空间复杂度是 (O(1)) ,属于常数阶空间复杂度,即算法运行所需额外空间与数据规模无关,是固定大小的。

2.

// 计算Fibonacci的空间复杂度?
// 返回斐波那契数列的前n项
long long* Fibonacci(size_t n)
{if (n == 0)return NULL;long long* fibArray = (long long*)malloc((n + 1) * sizeof(long long));fibArray[0] = 0;fibArray[1] = 1;for (int i = 2; i <= n; ++i){fibArray[i] = fibArray[i - 1] + fibArray[i - 2];}return fibArray;
}

动态分配了一个大小为 (n + 1) * sizeof(long long) 的数组 fibArray ,这部分空间随 n 线性增长。

其他变量(如 i 等)占用固定大小空间,不随 n 变化。

所以,该函数的空间复杂度为 O(n) ,因为动态分配的数组空间与输入规模 n 成线性关系。

3.

// 计算阶乘递归Fac的空间复杂度?
long long Fac(size_t N)
{if (N == 0)return 1;return Fac(N - 1) * N;
}

递归调用会在调用栈中开辟栈帧,每次递归调用 Fac(N - 1) 都会新增一个栈帧,直到 N == 0 时开始返回。递归深度最大为 N (从 N 递归到 0 ),所以栈空间的使用量与 N 成线性关系,空间复杂度为 O(N) 。

http://www.dtcms.com/a/266220.html

相关文章:

  • 【C++】访问者模式中的双重分派机制详解
  • 淋巴细胞激活靶点CD6
  • 【人工智能与机器人研究】优化YOLOv11模型:基于多尺度注意力机制的小目标检测性能提升研究
  • RRF (Reciprocal Rank Fusion) 排序算法详解
  • 【排序算法】
  • Vue3封装动态Form表单
  • 第二章-AIGC入门-开启AIGC音频探索之旅:从入门到实践(6/36)
  • 【学术写作+AI实战】株洲高校科研写作研修班全纪实:核心期刊编辑与AI专家的联合授课笔记
  • Web前端数据可视化:ECharts高效数据展示完全指南
  • 【JavaEE】计算机工作原理
  • JavaEE初阶第七期:解锁多线程,从 “单车道” 到 “高速公路” 的编程升级(五)
  • 运维打铁:企业云服务解决方案
  • openEuler 24.03 全流程实战:用 Ansible 5 分钟部署分布式 MinIO 高可用集群
  • Django+DRF 实战:从异常捕获到自定义错误信息
  • 深度分析:Microsoft .NET Framework System.Random 的 C++ 复刻实现
  • 切出idea窗口自动编译,关闭idea自动编译
  • WPF+HelixToolkit打造炫酷自定义3D贴图立方体盒子模型
  • 机器学习在智能供应链中的应用:需求预测与物流优化
  • Java技术深潜:从并发陷阱到云原生突围
  • web网页,在线%电商,茶叶,商城,网上商城系统%分析系统demo,于vscode,vue,java,jdk,springboot,mysql数据库
  • 警惕 Rust 字符串的性能陷阱:`chars().nth()` 的深坑与高效之道
  • 「AI产业」| 《中国信通院华为:智能体技术和应用研究报告》
  • P1202 [USACO1.1] 黑色星期五Friday the Thirteenth
  • Ubuntu Linux Cursor 安装与使用一
  • 成功解决运行:Django框架提示:no such table: django_session
  • 基于探索C++特殊容器类型:容器适配器+底层实现原理
  • 如何通过注解(@Component 等)声明一个 Bean?Spring 是如何找到这些注解的?
  • java微服务(Springboot篇)——————IDEA搭建第一个Springboot入门项目
  • 【基础算法】贪心 (二) :推公式
  • 封装一个png的编码解码操作