时间复杂度和空间复杂度

 重要的内容我都用彩笔标注了,易错点我也在文章中提醒了大家,大家放心食用


目录

1、前言

2、时间复杂度

2.1 时间复杂度的概念

2.2 大O的渐进表示法

练习一:

练习二:

练习三:

练习四:

练习五:

练习六:

练习七:

练习八:

3、空间复杂度

练习一:

练习二:

练习三:

练习四:

练习五:

4、复杂度的oj练习题:

3.1 消失的数字

3.2 轮转数组

 方法一(最基础的):

 方法二(yyds):


1、前言

算法在编写成.exe文件后,运行时需要耗费时间资源和空间资源。我们在衡量一个算法的好坏的时候,一般是从时间和空间两个角度去考察,即时间复杂度和空间复杂度。我们在做面试题时,很多题目会对这两个复杂度(尤其是时间复杂度)进行约束,因此我们要懂得如何去计算时间复杂度,才能控制和约束我们所写代码的时间和空间复杂度。


2、时间复杂度

2.1 时间复杂度的概念

算法的时间复杂度是一个函数(数学中的函数表达式),而算法中的基本操作的执行次数,则为算法的时间复杂度。

练习一下(づ ̄3 ̄)づ╭❤~

第一个双重循环的执行次数为N*N,第二个循环的执行次数是2*N,第三个while循环的执行次数10,Func1的时间复杂度精确为F(N)= N*N+2*N+10

但是准确的时间复杂度函数式,不方便在算法之间比较,我们应该对时间复杂度进行大概估算,这样才方便比较。

2.2 大O的渐进表示法

大O符号:是用于描述函数渐进行为的数学符号。

推导大O阶方法

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

使用大O的渐进表示法以后,Func1的时间复杂度为O(^{^{^{}}}N^{2}

常见的函数的时间复杂度为O(1)、O(N)、O(N^{2})、O(logN)

注意:最后一个的写法,因为在文本中对数不好书写,我们常简写成logN,最好不要写成lgN,我们只需要在看到lgN能知道讲的是logN就行了。

开始练习用大O渐进法算时间复杂度:

练习一:

 答案为:O(N);

练习二:

 答案为:O(N+M)(如果N>>M,答案就写O(N),如果M>>N,答案就写O(M), M \approx N,答案就写O(N)/ O(M));

练习三:

 答案:O(1);

练习四:

 答案:O(N);

补充一点:有些算法的时间复杂度存在最好、平均和最坏情况,在实际中一般情况关注的是算法的最坏运行情况。

像练习四中:最好的情况是一次就可以找到,时间复杂度就是O(1),最坏的情况需要N次才能找到,时间复杂度就是O(N),平均情况是需要N/2次找到,我们只关注最坏情况,时间复杂度为O(N)。

练习五:

 答案:O(N^{2})(提示:考虑最坏的情况,F(N)= N-1+N-2+N-3+......+1=N*(N-1)/2 )

练习六:

 答案:O(logN);

练习七:

 答案:O(N)

练习八:

答案:O(2^N);

 

 2^0+2^1+......+2^(N-2)+2^(N-1)=2^(N-1)-1 ,用大O的渐进表示法:O(2^N)

这里我说一嘴,这个代码并没有什么意义,因为执行效率太低了,O(2^N)执行次数非常大(N趋于无穷,2^N>N^2>N>logN),很容易造成stack overflow(栈溢出),我们一般不会这样写Fibonacci,下面是优化版本。

long long Fibonacci(size_t N)
{
	int f1 = 1, f2 = 1,f3;
	for (int i = 3; i <= N; i++)
	{
		f3 = f1 + f2;
		f1 = f2;
		f2 = f3;
	}
	if (N < 3)
		return 1;
	else
		return f3;
}

这个的时间复杂度为O(N),大大提高了执行效率。


3、空间复杂度

空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度。空间复杂度并不是计算程序占用了多少bytes的空间,而是计算额外开辟变量的个数,与时间复杂度相同,都采用大O渐进表示法。

注意:计算空间复杂度,一定要记住一句话空间可以叠加,时间不可以叠加

先上几个题练一练:

练习一:

 

 注意:空间复杂度计算的是主动创建的变量个数,被动接受的变量不需要计算

练习二:

 答案:O(N);

练习三:

 答案:O(N);

练习四:

答案:O(N);(时间是不可以叠加,空间是可以叠加的)

练习五:

答案:O(N)

这里我又要插一嘴(千万别想错辽),f1额外占用N+2个空间,main函数也是额外占用N+2个空间,因为第一次调用f1和第二次调用f1占用的空间都是一样的,空间可以叠加


4、复杂度的oj练习题

3.1 消失的数字

OJ链接:面试题 17.04. 消失的数字 - 力扣(LeetCode)

 答案:

 采用位运算,在循环时如果该数没有缺失,则a会与其进行两次异或运算,这两次则会抵消,但如果缺失了该数,最后的a就是所缺失的数(如果不懂,可以在评论区讨论)

3.2 轮转数组

OJ链接:189. 轮转数组 - 力扣(LeetCode)

 方法一(最基础的):

//方法一:
void rotate(int* nums, int numsSize, int k) 
{
	for (int i = 1; i <= k % numsSize; i++)
	{
		int tmp = nums[numsSize - 1];
		int n = numsSize;
		while (n-1)
		{
			nums[n - 1] = nums[n - 2];
			n--;
		}
		nums[0] = tmp;
	}
}

 这个能达到左旋的效果,但是不符合时间限制

方法二(yyds):

void reverse(int* a,int left,int right)
{
	int tmp=0;
	while (left <= right)
	{
		tmp = a[left];
		a[left] = a[right];
		a[right] = tmp;
		left++;
		right--;
	}
}
void rotate(int* nums, int numsSize, int k) 
{
	k = k % numsSize;  //这个可别忘了
	reverse(nums, numsSize - k, numsSize - 1);
	reverse(nums, 0, numsSize - k - 1);
	reverse(nums, 0, numsSize - 1);
}

数据结构很难,但我们一定要坚持住呀!

文章到此结束,喜欢我的文章的朋友点个赞再走吧!(更新不易,Thanks♪(・ω・)ノ)

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值