1. 衡量一个算法好坏的标准
通常通过时间复杂度、空间复杂度来评判,下面是一其他的些常用的标准。
正确性:算法是否能够正确解决问题,即输出是否符合预期。
可读性:算法代码是否易于理解和维护。
可扩展性:算法是否能够适应输入数据规模的增长,而不需要进行大规模的修改。
健壮性:算法在面对错误输入或异常情况时的稳定性和可靠性。
效率:算法在实际运行时的性能表现,包括CPU时间、内存使用等
了解就行
2. 算法效率
算法效率分析分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度,而空间效率被称作空间复杂度。 时间复杂度主要衡量的是一个算法的运行速度,而空间复杂度主要衡量一个算法所需要的额外空间
3. 时间复杂度
3.1 时间复杂度的概念
有些人认为算法的时间复杂度就是将代码运行的结束时间 - 运行开始的时间 ,这其实是不对的,当我们使用不同的电脑运行同一段代码,运行时间是不一样的,例如你用二十年前的电脑,我用现在的电脑,这没有可比性。
那我们应该如何计算算法的时间复杂度呢?
算法中的基本操作的执行次数,为算法的时间复杂度。(次数与时间成正比,所以我们可以用执行次数代表时间复杂度)
如果一个算法的时间复杂度低,那就意味着即使数据量增加,它也能很快完成任务;如果时间复杂度高,那么数据量一大,算法可能就会变得非常慢。
3.2 大O的渐进表示法
下面让我们计算这段代码的执行次数
void func1(int N){
int count = 0;
for (int i = 0; i < N ; i++) {
for (int j = 0; j < N ; j++) {
count++;
}
}
for (int k = 0; k < 2 * N ; k++) {
count++;
}
int M = 10;
while ((M--) > 0) {
count++;
}
System.out.println(count);
}
那么什么是大O渐进表示法呢?
随着 N 的值越来越大,F(N)越来越大,2N 和 10 都可以忽略不计。
实际上我们计算时间复杂度时,并不一定要精确的次数,只需要大概次数即可,于是在这里使用大O渐进表示法。
大O符号(Big O notation):是用于描述函数渐进行为的数学符号。
3.3 推导
- 用常数1取代运行时间中的所有加法常数.
- 在修改后的运行次数函数中,只保留最高阶项.
- 如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶.
这些要记住啊,其实用多了就会了
上述代码使用大O渐进表示法后的时间复杂度为 O(N的平方)(这里的N表示问题的规模)
时间复杂度分为
- 最坏情况:最大运行次数
- 平均情况:期望运行次数
- 最好情况:最小运行次数
一般讨论的是最坏情况的时间复杂度。
3.4 例子
- 冒泡排序的时间复杂度
void bubbleSort(int[] array) {
for (int end = array.length; end > 0; end--) {
boolean sorted = true;
for (int i = 1; i < end; i++) {
if (array[i - 1] > array[i]) {
Swap(array, i - 1, i);
sorted = false;
}
}
if (sorted == true) {
break;
}
}
}
有人看到有两个 for 循环肯定以为时间复杂度为 O( N的平方 ) ,其实不对。
解析如下图所示
略微潦草
- 二分查找的时间复杂度
int binarySearch(int[] array, int value) {
int begin = 0;
int end = array.length - 1;
while (begin <= end) {
int mid = begin + ((end-begin) / 2);
if (array[mid] < value)
begin = mid + 1;
else if (array[mid] > value)
end = mid - 1;
else
return mid;
}
return -1;
}
解析如下
潦草
- 递归
long factorial(int N) {
return N < 2 ? N : factorial(N-1) * N;
}
** 递归的时间复杂度 = 递归的次数 * 每次递归后代码执行的次数 **
解析如下
4. 斐波那契
int fibonacci(int N) {
return N < 2 ? N : fibonacci(N-1)+fibonacci(N-2);
}
very 潦草
我尽力啦
4. 空间复杂度(了解)
在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。