关于时间复杂度空间复杂度的理解
Posted textile
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于时间复杂度空间复杂度的理解相关的知识,希望对你有一定的参考价值。
对于非科班出身的人来说,在学习算法的时候经常会遇到的问题就是关于对事件空间复杂度的 理解。
「大 O 表示法」的准确的数学描述方式非常枯燥,我在这里就不贴出来凑字数了,其实大 O 表示法的意思挺简单的,就是表示:随着输入的值变化,程序运行所需要的时间与输入值的变化关系。
我们先看第一个代码,这是一个函数,输入一个数组,输出这个数组里元数的和。
int count(int a[], int n) { int result = 0; for (int i = 0; i < n; ++i) { result += a[i]; } return result; }
这里的时间复杂度是O(n),即随着n的增长,O(n)也随之线性增长,我们用O(n)来表示这种线性时间复杂度
接下来我们来看第二行代码
int binary_search(int A[], int key, int imin, int imax) { if (imax < imin) { return KEY_NOT_FOUND; } else { int imid = midpoint(imin, imax); if (A[imid] > key) return binary_search(A, key, imin, imid - 1); else if (A[imid] < key) return binary_search(A, key, imid + 1, imax); else return imid; } }
对于这个程序来说,如果它处理 N 个元素求和所花的时间是 T,那么它处理 N 2 个元素的和所花的时间是多少呢?是 T 2 吗?
如果头脑算不清楚,我们可以拿实际的数字来实验,二分查找每次(几乎)可以去掉一半的候选数字。所以假如 N = 1024,那么它最多要找多少次呢?答案是 10 次,因为 2^10 = 1024,每次去掉一半,10 次之后就只剩下唯一一个元素了。
好,这个时候,如果元素的个数翻一倍,变成 2048 个,那么它最多要找多少次呢?相信大家都能算出来吧?答案是 11 次,因为 2 ^ 11 = 2048。
所以在这个例子中,输入的元素个数虽然翻倍,但是程序运行所花的时间却只增加了 1,我们把这种时间复杂度要叫「对数」时间复杂度,用 O(logN) 来表示。
除了刚刚讲的「线性」时间复杂度和「对数」时间复杂度。我们还有以下这次常见的时间复度数。
「常数」时间复杂度,例如返回一个有序数组中的最小数,这个数因为始终在第一个位置,所以就不会受到数组大小的影响,无论数组多大,我们都可以在一个固定的时间返回结果。
「线性对数」时间复杂度,即 O(N*logN),这个复杂度比较常见,因为常见的高效的排序算法,都是这个时间复杂度,比如快速排序,堆排序,归并排序等。
之前我很多次在网上看到说把1000万次运算当做实际的1s来运算。我的计算机主频是2.5GHZ,所以每秒可以执行25亿次汇编指令,加入每次循环里面的代码可以产生250条汇编指令,才能够得到1s1千万次循环的结果,不是很确定,有机会可以yongxcode试一下
总结一下学习时间复杂度的知识对于我们的工作有什么用:
-
对于不同的数据规模,能够决策采用不同的解决方案。
-
了解什么情况下用暴力解法就能够解决问题,避免写复杂的代码。
-
在写代码之前,就能够预估程序的运行时间,从而可以知道是否能够满足产品需求。
-
在程序出现性能瓶颈时,能够有解决方案而不是抓瞎。
参考 https://www.cnblogs.com/mafeng/p/6831731.html
以上是关于关于时间复杂度空间复杂度的理解的主要内容,如果未能解决你的问题,请参考以下文章