算法设计是为了解决某个问题而开发的一个数学流程,算法分析是预测算法的一个性能。
1.使用大O标记来衡量算法效率
问题:两个算法执行相同的任务(比如 查找中的线性查找和二分查找),那个算法更好呐?
- 我们可以实现这两个算法,并运行程序得到执行时间。这种方式存在以下两个问题:
① 首先,计算机上同时运行这许多任务,一个特定的程序的执行时间是依赖于系统负荷的。
② 其次,执行时间以来与特定的输入。例如:线性查找和二分查找。如果要查找的元素恰好时线性表中的第一个元素,那么线性查找会比二分查找更快地找到改元素。
通过测量他们的执行时间来比较算法是非常困难的。 - 大O标记法:通过检查两个算法的执行时间的增长率来比较它们。
大O标记法(重点)
-
计算机科学家开发了一个独立于计算机和特定输入的理论方法来分析算法。该方法大致估计了由输入大小改变产生的影响。
通过这个方法可以看到随着输入大小的增长算法执行时间增长的有多快。 -
大O标记估算一个算法与输入规模相关的执行时间。
-
线性增长:如果,就称改算法使用了常量时间,使用符号O(1)表示。例如:
-
常量:如果输入规模与执行时间无关,就称改算法使用了常量时间,使用符号O(1)表示。例如:
2.确定时间复杂度
示例1:
for (int i = 0; i < n; i++) {
System.out.println(n);
}
执行语句System.out.println(n);
是一个常量时间c,因为循环执行了n次,所以其时间复杂度是:
T(n) = c * n = O(n)
- 时间复杂度为O(n2)的算法称为2次方阶算法,它体现了二次方的增长率。
示例2:
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.println(n);
}
}
执行语句System.out.println(n);
是一个常量时间c,外层循环执行n次。外层循环的每次迭代内层循环都会执行n次。所以其时间复杂度是:
T(n) = c * n * n = O(n2)
- 时间复杂度为O(n2)的算法称为2次方阶算法,它体现了二次方的增长率。
示例2:
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.println(n);
}
}
执行语句System.out.println(n);
是一个常量时间c,外层循环执行n次。外层循环的每次迭代内层循环都会执行n次。所以其时间复杂度是:
T(n) = c * n * n = O(n2)
- 时间复杂度为O(n2)的算法称为2次方阶算法,它体现了二次方的增长率。
示例3:二分查找
public static int commonBinarySearch(int[] arr,int key) {
int low = 0;
int high = arr.length - 1;
int middle = 0;
if (key < arr[low] || key > arr[high] || low > high) {
return -1;
}
while (low <= high) {
middle = (low + high) / 2;
if (arr[middle] > key) {
high = middle - 1;
} else if (arr[middle] < key) {
low = middle + 1;
} else {
return middle;
}
}
return -1;
}
二分查找的时间复杂度为T(n) = O(logn)。
- 时间复杂度为O(logn~)时间复杂度的算法称为对数算法,体现了呈对数增长的时间复杂度。对数算法中对数的底对增长率没有影响,因此可以忽略。