小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
以下维度来评估算法的优劣
正确性、可读性、健壮性 (是前提)
时间复杂度: 估算程序指令的执行次数
空间复杂度: 估算所需占用的存储空间
估算以下算法的程序指令(汇编指令)的执行次数:
我们不必较真汇编指令还是程序执行次数,因为我们是估算。
public static void test1(int n) {
// 汇编指令
// 1
if (n > 10) {
System.out.println("n > 10");
} else if (n > 5) { // 2
System.out.println("n > 5");
} else {
System.out.println("n <= 5");
}
// 1 + 4 + 4 + 4
for (int i = 0; i < 4; i++) {
System.out.println("test");
}
// 140000
// 时间复杂度O(1)
// 空间复杂度O(1)
}
public static void test2(int n) {
// O(n)
// 1 + 3n
for (int i = 0; i < n; i++) {
System.out.println("test");
}
}
public static void test3(int n) {
// 1 + 2n + n * (1 + 3n)
// 1 + 2n + n + 3n^2
// 3n^2 + 3n + 1
// O(n^2)
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.println("test");
}
}
}
public static void test4(int n) {
// 1 + 2n + n * (1 + 45)
// 1 + 2n + 46n
// 48n + 1
// O(n)
for (int i = 0; i < n; i++) {
for (int j = 0; j < 15; j++) {
System.out.println("test");
}
}
}
public static void test5(int n) {
// 8 = 2^3
// 16 = 2^4
// 3 = log2(8)
// 4 = log2(16)
// 执行次数 = log2(n)
// O(logn)
while ((n = n / 2) > 0) {
System.out.println("test");
}
}
public static void test6(int n) {
// log5(n)
// O(logn)
while ((n = n / 5) > 0) {
System.out.println("test");
}
}
public static void test7(int n) {
// 1 + 2*log2(n) + log2(n) * (1 + 3n)
// 1 + 3*log2(n) + 2 * nlog2(n)
// O(nlogn)
for (int i = 1; i < n; i = i * 2) {
// 1 + 3n
for (int j = 0; j < n; j++) {
System.out.println("test");
}
}
}
public static void test10(int n) {
//时间复杂度 O(n)
//空间复杂度 O(n)
int a = 10;
int b = 20;
int c = a + b;
int[] array = new int[n];
for (int i = 0; i < array.length; i++) {
System.out.println(array[i] + c);
}
}
大致估算了每个方法的 指令执行次数之后,来看一下 O(n) 、O(logn) 等表示的含义
大O 表示法:
一般用大O表示法来描述复杂度,它表示的是数据规模n对应的复杂度
忽略常数、系数、低阶
9 >> O(1)
2n + 3 >> O(n)
n^2 + 2n + 6 >> O(n^2)
4n^3 + 3n^2 + 22n + 100 >> O(n^3)
n^3代表n的3次方
对数阶的细节, 对数阶一般省略底数:
常数可忽略所以
统称为 logn
注意:大O表示法仅仅是一种粗略的分析模型,是一种估算,能帮助我们短时间内了解一个算法的执行效率
有了大O表示法,我们就不再需要 使用测试算法耗时之类的工具,来评价算法的优劣了。
常见的复杂度:
可以借助函数生成工具对比复杂度的大小
zh.numberempire.com/graphingcal…
空间复杂度的估算也是类似,不再赘述。
分析一下斐波拉契的时间复杂度:
// 时间复杂度 O(n)
public static int fib2(int n) {
if (n <= 1) return n;
int first = 0;
int second = 1;
for (int i = 0; i < n-1; i++) {
int sum = first + second;
first = second;
second = sum;
}
return second;
}
fib函数的时间复杂度分析:
“太极生两仪,两仪生四象,四象生八卦”
public static int fib(int n) {
if (n <= 1) return n;
return fib(n-1 ) + fib(n-2);
}
fib函数的时间复杂度为:
也就是 O(2^n) 2的n次方。
fib和fib2的差别有多大?
算法的优化方向
1.用尽量少的存储空间
2.用尽量少的执行步骤(执行时间)
3.根据情况,可以: 空间换时间 、 时间换空间
更多文章请关注我:
-
我的个人今日头条主页: www.toutiao.com/c/user/toke…
-
我的微信公众号:
- 我的掘金主页: