一、算法
算法就是为解决某一个特定问题而规定的系一列的操作,是一组有序的指令的集合。
数据结构与算法就是一对闺蜜
算法有五个特性:
- 输入: 一个算法有0个或多个输入
- 输出: 至少有一个输出,没有输出的算法没有意义
- 有穷性: 算法中执行指令的个数应该是有限的,执行是有穷的步骤后能结束
- 确定性: 对于特定的合法输入它的输出应该是唯一的
- 可行性: 算法能够实现,并且在有限的时间内完成。
算法设计要求
- 正确性: 没有语法错误,对于合法的输入产生满足要求的输出,对于特定的输入也能产生正确的输出。
- 可读性: 算法另一个目的是为了交流,方便阅读
- 健壮性: 对于不合理的要求 也能给出合理的提示信息,而不是崩溃
- 时间效率高与存储空间小
评价一个 算法性能的好坏,实际上就评价算法的资源占用率。 计算机最重要的资源就是时间和空间
使用时间复杂度衡量程序运行需要的时间
使用空间复杂度衡量程序所占内存的大小
二、时间复杂度
讨论计算机程序运行的时间可以采用以下方法:
- 事后统计
编程实现这个算法,统计所需要的时间。 - 事前分析
采用渐近时间复杂度分析估算
渐近时间复杂度,简称时间复杂度。 在进行算法分析时,语句总的执行次数,记作T(n),是关于问题规模n的函数,分析T(n)随着问题规模n的变化情况,确定T(n)的数量级。
T(n) = O(f(n)). 表示随着问题规模n的增大,算法执行的时间增长率和f(n)函数的增长率相同。f(n)是问题规模n的一个函数
随着输入规模n的增大,T(n)增长越慢的算法越好。
三、算法时间复杂度分析
算法1:
计算1+2+3+…+n的和,高斯算法
public static void sum2(int n){
int sum = n*(n+1)/2;
System.out.println("sun==" + sum);
}
顺序执行,时间复杂度,T(n) = O(1),是常数阶
算法2
计算1+2+3+…+n的和
public static void sum1(int n){
int sum = 0;
for(int i = 1;i <= n;i++){
sum += i;
}
System.out.println("sum==" + sum);
}
T(n) = O(n),线性阶
算法3:
public static void method1(int n){
int i = 1;
int count = 0;
while(i <= n){
i = i*2;
count++;
}
System.out.println("count==" + count);
}
循环控制变量i的值:1,2,4,8,16.。。。2的x次方。当执行了x次,i的值为2的x次方时 循环结束。循环条件 i<=n . 2的二次方<=n 不成立时循环退出
T(n) = O(logn)
算法4
public static void method2(int n){
int count = 0;
int s = 0;
while(s <= n){
count++;
s = s + count;
}
System.out.println("count==" + count);
}
假设循环执行x次, count变量 在循环过程中的值分别是:0,1,2,3…x
在执行完第x次后循环结束,s <= n 不成立时,s的值是:
s = 0+1+2+3…+x = x*(x+1)/2 = (x的2次方 + x)/2
T(n) = O(n的0.5次方)
算法5
public static void method3(int n){
int count = 0;
for(int i = 1;i <= n;i++){
for(int j = 1,j <= n;j++){
count++;
}
}
Sysem.out.println("count==" + count);
}
T(n) = O(n的2次方)
常见时间复杂度函数的增长率
抽象数据结构的操作复杂度
数组排序
四、空间复杂度
为了求解一个问题,在执行操作操作期间所需要的存储空间大小,不包括用来存储输入所需要的空间
记作:
S(n) = O(f(n))
结论:
算法的空间复杂度是以时间复杂度为上限的