-
如何衡量一个算法的好坏?
一个算法的好坏,主要看该算法的效率.而算法的效率分为2.
一是时间效率(时间复杂度),二是空间效率(空间复杂度) -
什么是时间复杂度?
在计算机科学中,算法的时间复杂度是一个函数,他定量描述了该算法的运行
时间. -
时间复杂度为什么不使用时间来衡量而使用基本语句的运行次数来衡量?
只有把程序放在机器上跑起来,才能知道.因此,过于麻烦.所以有了时间复杂度的概念,一个算法所花费的时间,与其中语句的执行次数成正比例,算法中基本操作的执行次数,为算法的时间复杂度. -
时间复杂度的O渐进表示法
. 1.用常数1取代运行时间中的所有加法常数
. 2.在修改的运行次数函数中,只保留最高阶项
3.如果最高阶项不是1,那么除以这个系数(即将系数置为1) -
时间复杂度的:最优、平均、最差情况,为什么时间复杂度看的是最差情况?
最优:任意输入规模的最小运行次数
最差:任意输入规模的最大运行次数
平均:任意输入规模的期望运行次数
如果最差情况下的复杂度符合我们的要求,我们就可以保证所有的情况下都不会有问题。 -
如何求解:二分查找、递归求阶乘、递归斐波那契的时间复杂度?
//二分查找
int BinarySearch(int* a, int n, int key) {
assert(a);
int left = 0;
int right = n - 1;
while (left < right) {
int mid = left + ((right - left) >> 2);
if (a[mid] == key) {
return mid;
}
else if (a[mid] > key) {
right = mid;
}
else {
left = mid + 1;
}
}
return -1;
}
//二分查找执行最好1次,最坏假设执行x次.
//在这n个数中n/2/2直到找到key,所以就有
//logn,所以该二分查找的时间复杂度为O(logn)
//递归求阶乘
long long Factorial(n) {
return n < 2 ? 1 : Factorial(n - 1) * Facorial(n);
}
//基本操作递归了n次,所以时间复杂度为O(n);
//单次递归中执行的次数*递归函数总递归数;
//递归求斐波那契
int Fib(n) {
return n < 3 ? 1 : Fib(n - 1) + Fib(n - 2);
}
//基本操作递归了2^n,
//所以时间复杂度为O(2^n);
-
什么是空间复杂度?
空间复杂度是一个算法在运行过程中临时占用存储空间大小的量度 -
如何求空间复杂度? 普通函数&递归函数
空间复杂度算的是变量的个数,计算规则与时间复杂度类似
/计算BubbleSort的空间复杂度
void BubbleSort(int* a, int n) {
assert(a);
for (int i = n; i>0; --i) {
int exchange = 0;
for (int j = 1; j < n; ++j) {
if (a[j-1] > a[j]) {
Swap(&a[j - 1], &a[j]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
return;
}
//该例中使用了常数个额外空间,根据大O渐进法
//其空间复杂度为O(1)
//计算Factorial的时间复杂度
long long Factorial(int N) {
return N < 2 ? N : Factorial(N - 1)*N;
}
//该函数中,共递归调用了N次,每次调用使用常
//数个空间,所以空间复杂度为O(N)
- 分析递归斐波那契数列的:时间、空间复杂度,并对其进行优化,伪递归优化—>循环优化
int Fib(int n) { return n < 3 ? 1 : (Fib(n - 1) + Fib(n - 2)); } //如上图所示,用二叉树的形式,递归了2^(n-3),所以 //时间复杂度为O(2^n)
//优化
//1.循环优化
int Fib(unsigned int n) {
if (n < 3)
return 1;
else {
int a=1, b=1;
int num =0;
for (int i = 3; i < n; ++i) {
num = a + b;
a = b;
b = num;
}
return num;
}
} //所以时间复杂度为O(n),空间复杂度为O(1)
//2.伪递归优化
long Fib(long n,long first,long second) {
if (n == 1 ||n==2)
return 1;
if (n == 3)
return first + second;
if (n > 3)
return Fib(n - 1, second, first + second);
}
//递归调用了n 次,单次递归执行了常数次
//所以时间复杂度为O(n),空间复杂度为O(1)
``