目录
1. 语句频度
算法运行时间=该语句重复执行的次数(语句频度)×该语句执行一次所需的时间。
2. 时间复杂度
定义:算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。
一个算法所花费的时间与其中语句的执行次数成正比例。所以算法中的基本操作的执行次数,为算法的时间复杂度。
时间复杂度的求解
例1
void Fun(int A[n][n],int B[n][n],int C[n][n]) { int i,j,k; for(int i=0;i<n;i++) //频度为n+1 { for(int j=0;j<n;j++) //频度为n*(n+1) { C[i][j]=0; //频度为n*n for(int k=0;k<n;k++)//频度为n*(n+1)*n { C[i][j]=C[i][j]+A[i][k]+B[k][j];//频度为n*n*n } } } }
频度之和:f(n)=2n*n*n+3*n*n+2*n+1
时间复杂度:O(n*n*n)
例2
void Func() { for(int i=0;i<n;i++) //频度为n { //...; } for(int i=0;i<m;i++) //频度为m { //...; } }
频度之和:f=m+n
时间复杂度:O(m+n)
例3
void Func() { int n=10; while(n--) //频度为10 { //...; } }
频度之和:f=10
时间复杂度:O(1)
最坏,最好,平均的情况
最好的情况执行1次
最坏的情况执行n次
平均执行(1+n)/2
但实际中一般考虑最坏的,所以时间复杂度=最坏的情况
二分查找
class Solution { public: int search(vector<int>& nums, int target) { int low=0,high=nums.size()-1; while(low<=high) { int mid=(high-low)/2+low; if(nums[mid]==target) return mid; else if(nums[mid]>target) high=mid-1; else low=mid+1; } return -1; } };
我们由二分查找的原理可知,查找1次,N被分为2份,查找2次,N被分为4份,由此我们假设查了f(x)次,此时N被分为2*f(x)份
2^f(x)=N,解得f(x)=logN,频度为f(n)=logN
时间复杂度O(logN)
递归
long long Factorial(int N) { return N<2?N:Factorial(N-1):N; }
时间复杂度:O(N!)
常见时间复杂度
常数阶 O(1)
对数阶 O(log2n)
线性阶 O(n)
线性对数阶 O(nlog2n)
平方阶 O(n^2)
立方阶 O(n^3)
k 次方阶 O(n^k)
指数阶 O(2^n)
3. 空间复杂度
空间复杂度指的是程序运行从开始到结束所需的存储空间的大小,程序所需的存储空间分为两部分:
- 固定部分:程序代码所占的存储空间,如常数、简单变量、定长成分(如数组元素结构成分、对象的数据成员等) 变量所占的存储空间。
- 可变部分:规模与实例特性有关的成分变量所占的存储空间、引用变量所占的存储空间、递归栈所用的存储空间、通过 malloc 和 ee 命今动态使用的存储空间。