什么是算法
- 算法是用于解决特点问题的一系列的执行步骤
斐波那契数
0 1 1 2 3 5 8 13 21. …
- 求第n个斐波那契数
- 第一种:递归
public static int fib(int n) { if(n<=1) { return n ; } return fib(n-1)+fib(n-2); } public static void main(String[] args) { System.out.println(fib(0)); System.out.println(fib(1)); System.out.println(fib(2)); } }
输出:011
但是有性能问题
- 第二种方法
public static int fib2(int n) {
if(n<=1) {
return n ;
}
int first= 0;
int second =1;
int sum = 0;
for (int i = 0; i < n-1; i++) {
sum =first + second;
first = second;
second = sum;
}
return sum;
}
一共计算的次数是当前第n个数减一次即n-1,当n>=1时,也就是已经从0 开始计算了,前两步的0+1是必然要走的。当两数相加,其值是下一次相加的第二个数,也就是second,第一次相加的第二个数则为第二次相加的第一个数也就是first.
如何评判一个算法的好坏
- 一般从正确性,可读性,健壮性
- 时间复杂度:估算程序指令的执行次数(执行时间)
- 空间复杂度:估算所需占用的存储空间
时间复杂度的估算
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");
}
// int i =0 算一次
//i <4 算4次
//i++ 要加4次, 算4次
//System.out.println("test"); 要执行4次,算4次
// 1 + 4 + 4 + 4
for (int i = 0; i < 4; i++) {
System.out.println("test");
}
//14
// O(1)
}
public static void test2(int n) {
// O(n)
// 1 + n+n+n
for (int i = 0; i < n; i++) {
System.out.println("test");
}
}
public static void test3(int n) {
//1+n+n+n*(1+n+n+n)=1+2n+n+3n^2=1+3n+3n^2
//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+n+n+n*(1+15+15+15)=1+48n
// 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 i+=i == i=i*2
for (int j = 0; j < n; j++) {
System.out.println("test");
}
}
}
public static void test10(int n) {
// 空间:O(n)
int a = 10;
int b = 20;
int c = a + b;
//要申请n个数组空间
int[] array = new int[n];
for (int i = 0; i < array.length; i++) {
System.out.println(array[i] + c);
}
}
递归是O(2^N)
一般用大 O表示法来描述 复杂度 ,它表示的 是数据规模 n 对应 的复杂度
- 忽略常数、系低阶
- 9>> O(1)
- 2n+3>> O(n)
- n2+2n+6>> O(n2)
- 4n3+3n2+22n+100>> O(n3)
- 写法上, n3等价于 n^3
- 注意:大 O表示法仅是一种粗略的分析模型,估算能帮助我们短时间内了解个执行效率
对数
- 阶一般省略底log2n=log29∗log9n
- 所以 log2n、log9n统称 为 logn
O(1) 1)< O( logn) < n) < nlogn) < n2) < n3) < 2n) < n!) < nn)
可以借助函数生成工具对比复杂度的大小
- https://zh.numberempire.com/graphingcalculator.ph php
数据规模小时
数据规模大时
多个数据规模时
O(n+k)