一、什么是时间复杂度?
算法时间复杂度定义:
在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。算法的时间复杂度,也就是算法的时间亮度,记作:T(n)=O(f(n))。它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间复杂度,简称为时间复杂度。其中f(n)是问题规模n的某个函数。
用0()来体现算法时间复杂度的记法,简称大O记法。
1.推导大O阶方法
1.1用常数1取代运行时间中所有加法常数。
1.2.在修改侯的运行次数函数中,只保留最高阶项。
1.3.如果最高阶项存在且不失1,则去除与这个项相乘的常数。得到的结果就是大O阶。
代码如下(示例):
for(i=1;i<=n;i++){
j=i;
j++;
}
这段代码的时间复杂度位:O(n)
2.常数阶O(1)
无论代码执行了多少行,只要是没有循环等复杂解雇,那这个代码的时间复杂度就是O(1),
代码如下(示例):
int i=1;
int j=2;
i++;
j++;
int n=i+l;
上述代码在执行的过程中,无论代码有多长,都可以用O(1)表示它的时间复杂度。
3.线性阶O(n)
for(i=1;i<=n,i++)
{
i=j;
j++
}
for循环里面的代码会执行n遍,因此它消耗的时间是随着n的变化而变化的,因此这类代码都可以用O(n)表示它的时间复杂度。
4.对数阶O(logn)
for(int i=1;i<=n;i*=2){
O(1)序列
}
从上面代码可以看到,在for循环里,每次都将i乘以2,乘完之后,i距离n就越来越近; 。 i:1 2 4 8 16 32......... i^次数=n,因此这类代码的时间复杂度为O(logn)
5.平方阶O(n^2)
平方阶O(n^2)更容易理解,如果把O(n)的代码再执行嵌套循环一遍,它的时间复杂度就是O(n^2)了
for(i=1;i<=n,i++){
for(j=1;j<=n;j++){
i=j;
j+=;
}
}
这段代码其实就是嵌套了2层n循环,它的时间复杂度就是O(n^2)
二、空间复杂度
类似于时间复杂度的讨论,一个算法的空间复杂度定义为该算法所耗费的存储空间,它也是问题规模n的函数。渐近空间复杂度也常常成为空间复杂度。
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的一个量度,同样反映的是一个趋势, 空间复杂度比较常用的有:O(1)、O(n)、O(n^2)
2.1 空间复杂度O(1)
如果算法执行所需要的临时空间不随着某个变量n的大小而变化,即此算法空间复杂度为一个常量,可表示为O(1)
int i=1;
int j=2;
i++;
j++;
int m=i+j;
代码中的i、j、m所分配的空间都不随着处理数据量变化,因此它的空间复杂度为O(1)
2.2空间复杂度O(n)
int [] m=new int[n]
for(i=1;i<=n;i++)
{
i=j;
j++;
}
这段代码,新new了一个数组出来,这个数组占用大小为n,因此,这段代码的空间复杂度为O(n)
2.2.1空间复杂度O(n)
排序:奇数在前,偶数在后
#include<stdio.h>
//#include<assert.h>
//void Ajust(int* arr, int len) {
// assert(arr != NULL && len > 0);
// int i = 0, j = len - 1;
// while (i < j) {
// while (arr[i]%2!=0) {
// i++;
// }
// while (arr[j]%2 == 0) {
// j--;
// }
// if(i<j){ // 判断条件
// int temp = arr[i];
// arr[i] = arr[j];
// arr[j] = temp;
// }
// }
//}
//int main() {
// int arr[] = { 1,2,3,4,5,6,7,8,9};
// int len = sizeof(arr) / sizeof(arr[0]);
// Ajust(arr, len);
// for (int i = 0; i < len; i++) {
// printf("%-5d", arr[i]);
// }
// return 0;
//}
空间复杂度:额外开辟了2快新内存,原来是n, 现在是n+n=2n,系数化为1,所以空间复杂度还是O(n).
算法优化:不开辟新内存,在原有基础上实现奇数在前,偶数在后。空间复杂度就为O(1)
总结
常用的时间复杂度耗费时间排序:
O(n^2)>O(n)>O(logn)>O(1)