本文介绍: 世上有两种耀眼的光芒,一种是正在升起的太阳,一种是正在努力学习编程的你!一个爱学编程的人。各位看官,我衷心的希望这篇博客能对你们有所帮助,同时也希望各位看官能对我的文章给与点评,希望我们能够携手共同促进进步,在编程道路上越走越远!提示:以下是本篇文章正文内容,下面案例可供参考好了,本篇博客这里结束了,如果有更好的观点,请及时留言,我会认真观看并学习。不积硅步,无以至千里;不积小流,无以成江海。

提示文章写完后,目录可以自动生成如何生成参考右边的帮助文档


前言

世上有两种耀眼的光芒,一种是正在升起的太阳,一种是正在努力学习编程的你!一个爱学编程的人。各位看官,我衷心的希望这篇博客能对你们有所帮助,同时也希望各位看官能对我的文章给与点评,希望我们能够携手共同促进进步,在编程的道路上越走越远!


提示:以下是本篇文章正文内容,下面案例可供参考

1.算法效率

1.1 如何衡量一个算法的好坏

如何衡量一个算法的好坏呢?比如对于以下斐波那契数列

long long Fib(int N)
{
 if(N < 3)
 return 1;
 
 return Fib(N-1) + Fib(N-2);
}

斐波那契数列递归实现方式非常简洁,但简洁一定好吗?那该如何衡量其好与坏呢?

1.2 算法复杂度

算法编写可执行程序后,运行需要耗费时间资源空间(内存)资源 。因此衡量一个算法的好坏,一般是从时间空间两个维度来衡量的,即时间复杂度空间复杂度
时间复杂度主要衡量一个算法运行快慢,而空间复杂度主要衡量一个算法运行需要额外空间计算机发展的早期,计算机存储容量很小。所以对空间复杂度很是在乎。但是经过计算行业的迅速发展计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。

2.时间复杂

2.1 时间复杂度的概念

时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句执行次数成正比例,算法中的基本操作执行次数,为算法的时间复杂度

即:找到某条基本语句问题规模N之间数学表达式,就是算出了该算法的时间复杂度。

// 请计算一下Func1中++count语句总共执行多少次?
void Func1(int N)
{
int count = 0;
for (int i = 0; i < N ; ++ i)
{
 for (int j = 0; j < N ; ++ j)
 {
 ++count;
 }
}
 
for (int k = 0; k < 2 * N ; ++ k)
{
 ++count;
}
int M = 10;
while (M--)
{
 ++count;
}
printf("%dn", count);
}

Func1 执行基本操作次数

实际中我们计算时间复杂度时,我们其实并不一定要计算精确执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法

2.2 大O的渐进表示

大O符号(Big O notation):是用于描述函数渐进行为数学符号

 推导大O阶方法
1、用常数1取代运行时间中的所有加法常数
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。

 另外有些算法的时间复杂度存在最好、平均和最坏情况:
 最坏情况:任意输入规模的最大运行次数(上界)
 平均情况:任意输入规模的期望运行次数
 最好情况:任意输入规模的最小运行次数(下界)
 例如:在一个长度为N数组搜索个数x
 最好情况:1次找到
 最坏情况:N次找到
 平均情况:N/2次找到

在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)

2.3常见时间复杂度计算举例

实例答案分析
1. 实例1基本操作执行了2N+10次,通过推导大O阶方法知道,时间复杂度为 O(N)
2. 实例2基本操作执行了M+N次,有两个未知数M和N,时间复杂度为 O(N+M)
3. 实例3基本操作执行了10次,通过推导大O阶方法,时间复杂度为 O(1)
4. 实例4基本操作执行最好1次,最坏N次,时间复杂度一般看最坏,时间复杂度为 O(N)
5. 实例5基本操作执行最好N次,最坏执行了(N*(N+1)/2次,通过推导大O阶方法+时间复杂度一般看最
坏,时间复杂度为 O(N^2)
6. 实例6基本操作执行最好1次,最坏O(logN)次,时间复杂度为 O(logN) pslogN在算法分析表示是底
数为2,对数为N。有些地方会写成lgN。(建议通过折纸查找方式讲解logN是怎么计算出来的)
7. 实例7通过计算分析发现基本操作递归了N次,时间复杂度为O(N)。
8. 实例8通过计算分析发现基本操作递归了2^N次,时间复杂度为O(2^N)。(建议画图递归栈帧的二叉树
讲解

3.空间复杂度

空间复杂度也是一个数学表达式,是对一个算法在运行过程临时额外占用存储空间大小的量度
空间复杂度不是程序占用多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量个数。空间复杂度计算规则基本跟时间复杂度类似,也使用大O渐进表示
注意:函数运行时所需要的栈空间(存储参数局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请额外空间来确定

实例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] &gt; a[i])
 {
 Swap(&amp;a[i-1], &amp;a[i]);
 exchange = 1;
 }
 }
 if (exchange == 0)
 break;
 }
}

实例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;
}

实例答案分析
1. 实例1使用常数额外空间,所以空间复杂度为 O(1)
2. 实例2动态开辟了N个空间,空间复杂度为 O(N)
3. 实例3递归调用了N次,开辟了N个栈帧,每个栈帧使用常数个空间。空间复杂度为O(N)

4. 常见复杂度对比

一般算法常见的复杂度如下

5. 复杂度的oj练习

3.1消失数字OJ链接https://leetcode-cn.com/problems/missing-number-lcci/

数组nums包含0n的所有整数,但其中缺了一个。请编写代码找出那个缺失整数。你有办法在O(n)时间内完成吗?

代码演示

3.2 旋转数组OJ链接https://leetcode-cn.com/problems/rotate-array/

给定一个整数数组 nums,将数组中的元素向右轮转 k 位置,其中 k 是非负数。

代码演示

代码演示

补充之前的一些零散知识

realloc()函数如果是异地扩容的话,原来的空间不需要自己释放,函数自己把原来的空间释放掉。

free()函数要释放空间的话,不能分期付款,意思是要整块空间释放,不能一个一个空间释放。


总结

好了,本篇博客这里结束了,如果有更好的观点,请及时留言,我会认真观看并学习
不积硅步,无以至千里;不积小流,无以成江海。

原文地址:https://blog.csdn.net/2301_79585944/article/details/134758450

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_34894.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注