Big O notation大零符合 入门讲解
2017-07-11 21:04
435 查看
Big O notation大零符号一般用于描述算法的复杂程度,比如执行的时间或占用内存(磁盘)的空间等,特指最坏时的情形。
Linus Torvalds说过“Talking is cheap, show me the code.”,那我们直接从代码(Python)上来学习Big O吧。
O(1)
无论输入参数是什么,这个函数就只执行一次,所以它的复杂度为O(1)。
O(N)
这里有一个for循环,如果运气好就执行一次(elements里第一个值就跟value一样),运气不好就要执行N次(N等于elements的长度,碰巧elements里最后一个值跟value一样),因为Big O是表示最坏时情形,所以这个函数的复杂度为O(N),好理解吧。
O(N2)
这里有两个嵌套的for循环,所以执行最多的次数肯定为两个for循环次数相乘,即N*N(N等于elements长度),所以这个函数的复杂度为O(N2)。
O(2N)
这是计算斐波那契数的函数,用递归方式实现,不太容易一下就看出执行了多少次。不要紧,我画了个图,这样就方便直观了。
容易看出执行多少次了吧,即2的N次方,所以这个函数的复杂度为O(2N)。
对了,斐波那契函数是什么鬼,看看下面这个图你立马就明白了。
O(logN)
是不是一看log(对数)就头大,其实没那么复杂,在看例子前我们先复习复习高中知识,什么是log。
如果x的y次方等于n(x>0,且x不等于1),那么数y叫做以x为底n的对数(logarithm)
记作logxn=y。其中,x叫做对数的底数。
1.底数为10时,写为lg;
2.底数为e时,称为自然对数写为ln,这个在高等数学中用的很多;
3.底数为2时,主要用在计算机中,写为log,也就是不写底数;
所以我们说的logN其实就是log2n
我们以Binary Search(也叫拆半查询和二分查询)为例,感觉查询过程就跟切西瓜一样,先中间切一刀,然后选一块,再在选定的半个西瓜上再来一刀,再决定选哪块,再切再选,最后找到满意的,即1/2,1/4,1/8,1/16…这样下去。以下是算法脚本
以下是测试程序
其实这样一刀一刀的找就是2的倍数关系,比如切了3刀找到,那就有8块了(其实是4块,因为你只切选中的那一块,但为了计算方便,我们就当把西瓜都切了),即2的3次方,如果切5刀找打,那就有32块,即2的5次方,所以这个算法的时间复杂度就是O(log2N),即O(logN)。
Linus Torvalds说过“Talking is cheap, show me the code.”,那我们直接从代码(Python)上来学习Big O吧。
O(1)
def isFirstElementNull(elements, value): return elements[0] == value #print isFirstElementNull(["1","2"],"1")
无论输入参数是什么,这个函数就只执行一次,所以它的复杂度为O(1)。
O(N)
def containsValue(elements, value): for e in elements: if e == value: return True return False #print isFirstElementNull(["1","2"],"1")
这里有一个for循环,如果运气好就执行一次(elements里第一个值就跟value一样),运气不好就要执行N次(N等于elements的长度,碰巧elements里最后一个值跟value一样),因为Big O是表示最坏时情形,所以这个函数的复杂度为O(N),好理解吧。
O(N2)
def containsDuplicates(elements): for m in range(len(elements)): for n in range(len(elements)): if (m != n) and elements[m] == elements : return True return False #print containsDuplicates(["1","2","3","2"])
这里有两个嵌套的for循环,所以执行最多的次数肯定为两个for循环次数相乘,即N*N(N等于elements长度),所以这个函数的复杂度为O(N2)。
O(2N)
def fibonacci(num): if num < 2: return num return fibonacci(num - 2) + fibonacci(num - 1) #print fibonacci(5)
这是计算斐波那契数的函数,用递归方式实现,不太容易一下就看出执行了多少次。不要紧,我画了个图,这样就方便直观了。
容易看出执行多少次了吧,即2的N次方,所以这个函数的复杂度为O(2N)。
对了,斐波那契函数是什么鬼,看看下面这个图你立马就明白了。
O(logN)
是不是一看log(对数)就头大,其实没那么复杂,在看例子前我们先复习复习高中知识,什么是log。
如果x的y次方等于n(x>0,且x不等于1),那么数y叫做以x为底n的对数(logarithm)
记作logxn=y。其中,x叫做对数的底数。
1.底数为10时,写为lg;
2.底数为e时,称为自然对数写为ln,这个在高等数学中用的很多;
3.底数为2时,主要用在计算机中,写为log,也就是不写底数;
所以我们说的logN其实就是log2n
我们以Binary Search(也叫拆半查询和二分查询)为例,感觉查询过程就跟切西瓜一样,先中间切一刀,然后选一块,再在选定的半个西瓜上再来一刀,再决定选哪块,再切再选,最后找到满意的,即1/2,1/4,1/8,1/16…这样下去。以下是算法脚本
public int binarySearch(int array[],int key) { int begin = 0; int end = array.length - 1; while (begin <= end) { int mid = begin + (end - begin) / 2; if (array[mid] > key){ end = mid - 1; } else if (array[mid] < key){ begin = mid + 1; }else{ return mid; } } return -1; }
以下是测试程序
int[] a1 = {1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77,88,99,100}; int result = binarySearch(a1, 4); System.out.println(result); //output: 3
其实这样一刀一刀的找就是2的倍数关系,比如切了3刀找到,那就有8块了(其实是4块,因为你只切选中的那一块,但为了计算方便,我们就当把西瓜都切了),即2的3次方,如果切5刀找打,那就有32块,即2的5次方,所以这个算法的时间复杂度就是O(log2N),即O(logN)。
注意,时间复杂度是个近似值,比如O(2N)就是O(N),O(3N+5)就是O(N),这个值要表达的是个复杂度趋势,记住这点很重要。
相关文章推荐
- 第二章 Big O notation 试题以及讲解 (包会)
- Postman安装与入门讲解
- n!的近似值 (stirling approximation)与 大O记法(big -O- notation)
- 算法竞赛之高精度以及部分组合的入门讲解
- htmlparser入门讲解
- GBDT 入门教程之原理、所解决的问题、应用场景讲解
- Dubbo入门基础与实例讲解
- Scrapy简单入门及实例讲解
- SpringMVC入门实例及详细讲解
- jQuery入门及各种选择器讲解
- JAVA-23-HTML入门、常用标签讲解
- 详细讲解Quartz如何从入门到精通 (4)
- Cocos2d-x入门教程(详细的实例和讲解)
- Docker入门与实战讲解
- Call指令和Ret指令讲解03 - 零基础入门学习汇编语言50
- iOS 数据库篇(一) CoreData 认识与入门---原理讲解篇
- react的入门讲解
- .Net下的委托入门讲解
- C语言嵌入informix基础入门示例讲解
- web serverice入门讲解