赞
踩
目录
2.总结:大O渐进表示法(大O符号:描述函数渐进行为的符号)
算法是解决一个问题的方法,一个问题可对应多种算法,算法在编写成可执行程序后,需要消耗一定的时间资源和空间(内存)资源。因此评价一个算法的好坏,一般从时间和空间两个维度来考虑,及时间复杂度和空间复杂度。
时间复杂度主要是衡量一个算法运行的快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间,在计算机早期,计算机储存容量是很小的,所以对空间复杂度很在乎。但随着技术的发展计算机的容量已经达到了一个很高的程度(摩尔定律:计算机大约每年翻一倍(但是现在技术到达瓶颈,已经失效))。所以我们现在不用特别关心一个算法的空间复杂度,现在更多关注的时间复杂度。
时间复杂度的定义:在计算机学科中,算法的时间复杂度是一个函数(F(N)=2*N……+N),它定量的描述一个算法运行所需要的时间,一个算法执行消耗的时间,理论上,是不能够算出来的,只有将程序发放在编译器上跑起来,才知道它运行的时间,但是在解决一个问题是要把每一个算法都敲出来上机测试吗?当然可以,但是!很麻烦,浪费时间,所以才有了时间复杂度这个分析方法。一个算法花费的时间与其中语句执行的次数成正比,所以算法的基本执行次数,为算法的复杂度。
即:找到某条基本语句与问题N之间的数学表达式,就是算出了该算法时间的复杂度。
不难看出执行次数的函数F(N)=N……2+2N+10,当N取不同值时执行次数也不同,各项对次数的影响各不相同,随着N的不断增大(不用考略N值很小的情况,计算机的cpu主频单位时间内计算次数上亿次),后两项对函数的大小影响微乎其微,所以就可忽略掉,只取最高次数项--N……2,这样就可以大概估算出语句执行的次数,这里介绍一个方法,大O渐进表示法来表示量级,用函数最高项次数的表达式,忽略前面自带系数,统一为1,上面函数可表示为O(N……2)。
例二:
答案是O(m+n),当m远大于n时呢?O(m),反之为O(n)。
例子:
答案是O(100)吗?其实不是的,如果一个算法的执行次数为常数,那统一表达为O(1)。
ps:上面例子可用clock函数来看程序执行时间。
1.所有常数都用常数1表示
2.只保留最高阶项
3.如果最高阶项存在且不是1,则去除这个项的系数,得到的结果就是大O阶。
4.常数阶表示为O(1)。
常见复杂度阶级如下:
在这个函数中的时间复杂度是多少呢?最好的情况是一次就能找到,最坏的情况是最后一次才找到N次,这两种情况取哪一种,还是两种情况的折中?这里需要记住的就是,在衡量一个算法时间复杂度时,关注的是算法的最坏情况,所以上述函数的复杂度是O(N)。
例子1:
消失的她!(力扣上的题)
思路一:先排序,循环遍历如果后一个数字比前一个数字大2,就找到结果了,但是时间复杂度为O(N……2)
思路二:0到N的和减去数组值的和,差值为答案,复杂度为O(N),但是如果N太大可能会溢出。
思路三:用0异或数组和0到N的值,返回X,复杂度为O(N)。
例子2:
旋转数组(来自力扣)
提示真实旋转值为k%=numsSize;
思路一:暴力解决,外循环交换(最坏情况n-1),内循环后移,时间复杂度O(N……2)。
思路二:空间换时间,创建新数组将后k个换到新数组的前面,前numsSize换到新数组的后面。
思路三:三段逆置,前n-k个逆转,后k个逆转,再整体逆转,时间复杂度O(N)。
有些程序的时间复杂度不能直接数循环,
这个程序的时间复杂度是O(N)吗?
不是!程序执行x次,即有等量关系2……x等于N,解出X=log(2)N,所以时间复杂度为O(log(2)N)。
例子:二分查找
最坏的情况是:n/2/2/2/2/2...../2=1,执行了x=log(2)N次,所以时间复杂度为O(log(2)N).
ps:log阶级的复杂度一般底数都是2,所以O(log(2)N)可以简写为O(logN)。
二分法相对于暴力查找法有很大的优势,当n取很大很大的值时,二分查找需要几十次的查找就可以查出来,但是暴力查找需要n次。
但是也有很大的缺点:
1.数组需要排序,对于很大的数,排序也需要消耗很多时间资源。
2.实现增删查改很麻烦,就像循序表一样,消耗很多资源。
在后续的学习中,二叉树可以解决这个缺点。
到这,通过一些简单概念和例子的介绍大概知道的时间复杂度是用来度量算法程序执行次数的量,在后续解决一个实际的问题的时候,可以先从多个思路分析这个这个问题,计算出算法的时间复杂度,对比,找出时间复杂度的最低算法来实现(但是时间复杂度不一定是越低越好)。
下一篇会用很短的篇幅来介绍空间复杂度(因为前面提到空间复杂度不是那么的重要在现在的技术下,但是像嵌入式方面还是很需要的),紧接着就是对链表学习的总结。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。