本篇内容介绍了“怎么理解时间复杂度和空间复杂度”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
创新互联建站坚持“要么做到,要么别承诺”的工作理念,服务领域包括:成都做网站、成都网站制作、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的南岔网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!
我们经常可以看到这样的描述:软件=数据结构+算法,可见算法基础对于一个程序员的重要性。算法中,有两个基本概念:时间复杂度和空间复杂度。
时间复杂度:描述算法执行消耗的时间,时间越短,时间复杂度越低,算法越优秀;
空间复杂度:描述算法执行所占用的内存空间,占用内存越少,空间复杂度越低,算法越优秀;
因此,时间复杂度和空间复杂度是评价一个算法性能的主要指标。那么如何计算一个算法的时间复杂度和空间复杂度呢?
简单理解,计算时间复杂度就是评估一个算法完成后执行了多少行代码,也就是算法所消耗的时间,但是该如何用数学的方式其表示出来呢?
假设现在有个一个算法需要执行n次运算,我们用T(n)表示,n即表示算法的规模(比如n=10时,循环输出10次Hello World;n=100时,循环输出100次Hello World)。如果假设存在一个函数f(n),表示随着n的变化,算法需要执行的次数,当T(n)=O(f(n)),那么O(f(n))即为算法的时间复杂度。
比如,一个普通的循环:
public int calc(int n) { int total = 0; for (int i = 0; i < n; i++) { total += i; } return total; }
当n越大,循环的次数越多,那么耗费的时间也就越大,也就是f(n)随着n线性增长。那么该算法的执行时间T(n)=O(n),即时间复杂度为O(n)。
再比如,一个双层循环:
public int calc(int n) { int total = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { total += j; } } return total; }
外层循环每循环一次,内层循环就循环了n次,那么代码总循环次数就是n*n。那么该算法的执行时间T(n)=O(n^2) ,即时间复杂度为O(n^2)。
一般来说,时间复杂度是用来评估随着n的增大,算法执行需要消耗时间的增速,而不是精确计算消耗的时间,事实上也无法精确计算。既然是评估,那么f(n)函数我们只需要保留对消耗时间影响最大的因子即可。
例如,有一个f(n)=2*n^3函数,系数2对f(n)函数的增速影响就不大,所以该算法的时间复杂度T(n)=O(n^3),即忽略常量系数对增速的影响。
再比如,在一个没有循环的代码块里,只有三行输出代码:
public void print() { System.out.println("Hello 河先森"); System.out.println("Hello 河先森"); System.out.println("Hello 河先森"); }
即T(n)=3,是一个常数,而常数对增速的影响是可以忽略的,那么该代码块的时间复杂度就是O(1)。
再来看一个例子,计算下面代码块的时间复杂度:
public void print(int n) { for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { System.out.println("Hello 河先森"); } } }
当i=0时,内层循环了n次,当i=1时,内层循环了n-1次,以此内推,当i=n-1时,内层循环了1次。那么总的循环次数T(n)=n+(n-1)+(n-1)+...+1=n(n+1)/2=n^n/2+n/2,忽略常数项和对增速影响不大的因子,只保留影响最大的因子,那么该算法的时间复杂度即为O(n^2)。
常见的时间复杂度量级:
常数阶O(1)
对数阶O(logN)
线性阶O(n)
线性对数阶O(nlogN)
平方阶O(n²)
立方阶O(n³)
K次方阶O(n^k)
指数阶(2^n)
以上算法时间复杂度中,随着n的增大,f(n)增速越快,说明算法的效率越低。即算法耗费的时间O(1) < O(logN) < O(n) < O(nlogN) < O(n²) < O(n³) < O(n^k) < O(2^n)。
如果想在一个数组中找到一个数,最简单的方法就是循环遍历:
public boolean search(int m) { int[] arr = new int[]{3, 5, 7, 1, 2, 6, 4, 9}; for (int i = 0; i < arr.length; i++) { if (m == arr[i]) { return true; } } return false; }
如果要查找的是数是数组的第一个数(本例子中的3),那么只需要一次循环就能找到,时间复杂度为O(1)。但是如果要查找的数在数组最后位置(本例中的9),那么必须要经过arr.length次循环,时间复杂度为O(n),n为数组的长度。那么这段代码代码块的时间复杂度到底是多少呢?
一般在没有特殊说明的情况下,时间复杂度都是指最坏的时间复杂度,因为没有比这更坏的情况了。所以这段代码块的时间复杂度为O(n)。
时间复杂度描述的是算法消耗时间趋势,同理,空间复杂度则是描述算法在运行时临时内存消耗的趋势,一般用 S(n) 来定义,记作S(n)=O(fn)。
至于评价算法的具体好坏,就要具体情况具体分析了。有时我们会拿时间换空间,有时会去拿空间换时间,有时则需要同时考虑时间和空间复杂度。
总之,具体问题具体分析,但是我们一定要理解时间复杂度和空间复杂度的分析过程。
“怎么理解时间复杂度和空间复杂度”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!