大学的数据结构,学的确实不怎么样,算法这一块,也有待提高,每次百度一些BAT笔试题,看到什么时间复杂度,空间复杂度都是一头雾水。最近找实习工作不是很顺利,需要实习生的公司本来就不多,很多公司看到学校咋样,就直接PASS你,不给你机会。不过没关系,一切都会好起来的。趁现在每天时间还算自由,多看看书,争取机会到来的时候一把抓住。开始正题。
先来明确2个名词的概念:
时间复杂度:
书上对于时间复杂度的定义是这样的:在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况进而确定T(n)的数量级。算法的时间复杂度,也就是算法的时间量度,记作T(n)=O(f(n))。它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度,简称时间复杂度。其中f(n)是时间规模n的某个函数。
如果看的头疼,暂时理解为是衡量一个算法执行需要的计算工作量。
空间复杂度:
书上定义的是通过计算算法所需的存储空间实现,算法空间复杂度的计算公式S(n) = O(f(n)),其中,n为问题规模,f(n)为语句关于n所占存储空间的函数。
暂理解为是指执行这个算法所需要的内存空间。
定义理解完了,书上的理解不了,就理解成简单的。后面深入了解的时候,也许就理解作者的定义了,时间复杂度用的比较多,也较为丰富,我们先来看看时间复杂度。再看时间复杂度之前,我们需要看3个准则。看不懂没关系,知道有他们就好了,后续的内容慢慢就懂了。
如何推导大O阶:
(1)用常数1取代运行时间中的所有加法常数,如O(1)。
(2)在修改后的运行次数函数中,只保留最高阶数,如n²+n 为 O(n²)。
(3)如果最高阶数存在且不是1,则去除与这个项相乘的常数,如3n³ 为 O(n³)。
看一个算法。称为常数阶
- int sum = 0, n = 200; // 执行一次
- sum = (1 + n) * n / 2; // 执行一次
- System.out.println(sum); // 执行一次
看第二个算法。称为线性阶
- for(int i = 0; i < n; i++){
- 时间复杂度为O(1)的程序步奏
- }
看第三个算法。称为对数阶
- int count = 1;
- while(count < n){
- count = count * 2;
- }
看第四个算法。称为平方阶
- for(int i = 0; i < n; i++){
- for(int j = 0; j < n; j++){
- 时间复杂度为O(1)的程序步奏
- }
- }
- for(int i = 0; i < n; i++){
- for(int j = i; j < n; j++){
- 时间复杂度为O(1)的程序步奏
- }
- }
常用时间复杂度所耗费时间从小到大依次为:O(1) < O(logn) < O(n) < O(nlogn) < O(n²) < O(n³) < O(2n) < O(n!) < O(n²)
至于空间复杂度,就是一般拿空间换时间了,算法的空间复杂度一般也以数量级的形式给出。如当一个算法的空间复杂度为一个常量,即不随被处理数据量n的大小而改变时,可表示为O(1);当一个算法的空间复杂度与以2为底的n的对数成正比时,可表示为O(log2n);当一个算法的空间复杂度与n成线性比例关系时,可表示为O(n)。用的好像并不多,通常没有说明的时候,一般都是问时间复杂度,时间复杂度是一个非常重要的概念,直接影响到我们的代码执行效率。