1.怎样衡量一个算法的好坏
衡量一个算法的好坏可以通过算法效率来判断,算法效率又分为空间效率和时间效率,也就是空间复杂度和时间复杂度,时间复杂度主要衡量算法的运行速度,而空间复杂度衡量一个算法所需要的额外空间.
2.什么是时间复杂度
简单地说就是描述运行时间,通过函数表示的,算法中基本操作的执行次数为算法的时间复杂度.
3.时间复杂度为什么是使用基本语句的运行次数来衡量?
如果我们使用时间来表示算法的时间复杂度,那么我们只有在程序运行起来才能测算时间,每个算法都要上机测试的话就会很麻烦,为了在不运行时就能看出来一个算法的效率,就有了时间复杂度这一分析方式.一个算法所花费的时间与基本语句执行次数成正比,所以可以让基本操作的执行次数为算法的时间复杂度.
4.O渐进表示法
O是描述函数渐进行为的数学符号.我们在计算时间复杂度的时候不用太精确,比如下面的例子
void Fun1(int n) {
int count = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; i < n; ++j) {
++count;
}
}
for (int x = 0; x < 2 * n; ++x) {
++count;
}
for (int m = 0; m < 10; ++m) {
++count;
}
}
如上面的例子,Fun1的基本语句++count执行了
F(N)=n^2+2n+10 次
-
当N=10时 F(N)=130
-
当N=100时 F(N)=10210
-
当N=1000时 F(N)=1002010
可以看出执行次数越多2n和10所表示的执行次数比重越来越小,所以不用太精确
把F(N)=n^2+2n+10使用O表示法可以表示为
O(N^2)
O去掉了对结果影响不大的数,所以在用大O阶表示时间复杂度的时候可以遵守以下规则
(1)去掉常数项
(2)只保留最高阶项
(3)去掉最高阶项的系数
5.时间复杂度的三种情况
最好 平均 最坏
时间复杂度看最坏情况
- 几种函数的时间复杂度
(1.)二分查找
int BinarySearch(int* a, int n, int key) {
int left = 0;
int right = n - 1;
while (left < right) {
int mid = n / 2;
if (a[mid] == key) {
return mid;
}
else if (a[mid] < key) {
left = mid + 1;
}
else if (a[mid] > key) {
right = mid;
}
}
return -1;
}
总共N个元素,每次一半,就是N/2,N/4,N/8…N/2^K(K是循环的次数)
k=log2n,(是以2为底,n的对数)
时间复杂度是O(logN)
(2).递归求阶乘
long long Factorial(size_t N) {
return N < 2 ? N : Factorial(N - 1)*N;
}
这是大佬的代码
咱们来求时间复杂度
首先,递归函数的时间复杂度是 单次递归函数中基本语句的执行次数*递归总次数
这是一个递归程,可以看出每递归一次n的规模小1,所是结果是线性的。
- 空间复杂度
空间复杂度就是一个程序在运行过程中临时占用储存空间大小的度量
下面看个例子
void BubbleSort(int* a, int n) {
for (int end = n; end > 0; --end ) {
int exchange = 0;
for (int i = 1; i < end; ++i) {
if ( a[i-1] > a[i] ) {
Swap(&a[i - 1], &a[i]);
exchange = 1;
}
}
if (exchange == 0) {
break;
}
}
}
上面的冒泡排序使用了常数个额外空间,所以空间复杂度是O(1);