2020.2.11
12:22
评估算法性能:
①:主要评估问题的输入规模n与元素的访问次数f(n)的关系。
②:大O符号:忽略非主体的部分,如常数项,低阶项。
③:O(g(n)):表示这个算法有一个渐进上界,这个渐进上界为g(n),算法的运行时间f(n)趋近并且
小于等于这个g(n)。
举例:
①:
for(int i=0;i<=n;i++) {
k+=5;
}
(复杂度:O(n) 线性复杂度)
②:
for(int i=1;i<=0;i++){
for(int j=1;j<=i;j++){
k=k+i+j;
}
}
(复杂度:O(n^2) 平方复杂度)
③:
int count=1;
while(count<n){
count=count*2;
}
(复杂度:O(lgn)对数复杂度)
-
n!的上界是n^n,增长的速度很快,意味着单位时间内可以求解的问题很小,超慢。
-
2^n 这样的指数函数增长非常快,这种算法可以认为超慢。
-
o(n^2)算法增长快,算法慢,至少优化到nlgn, o(n^2)的有冒泡排序,直接插入排序,选择排序
-
nlgn认为是及格的算法,一般分治法可以缩小层数为lgn,而每层的复杂度一般为o(n),例如归并排序,快速排序算法
-
o(n)叫做线性算法,算法比较优秀,一般求解连续求和和最大子数组的线性解
-
o(sqrt(n)),比上一个更好,但是很少。
-
lgn是很优秀的算法,比如二分法查找,但是这种往往对输入的数据格式有要求
-
最后一种是常量,无论规模怎么扩大,都花固定的时间,这是极其少的高效的算法。
几种复杂度图解:
二分法与直接法的正面对比:
(忽略我的类名起的是中文的,英文类名一多我就记不住了)
package LanQiaoKnowledge;
public class 算法性能比较 {
//顺序查找
static void Search1(int []arr, int key) {
for(int i=0;i<arr.length;i++) {
if(arr[i]==key) {
System.out.println("找到了,元素在数组中的位置为:"+(i+1));
}else {
continue; //跳转
}
}
}
//二分法查找
static int Search2(int []arr,int low,int high,int key) {
if(low>high) {
return -1;
}
// int mid=low+((high+low)>>1); //利用移位来防止栈溢出,比较高效
int mid=(low+high)/2; //下标
int midval=arr[mid]; //中间元素
if(midval<key) {
return Search2(arr,mid+1,high,key); //右边
}
else if(midval>key) { //左边
return Search2(arr,low,high-1,key);
}
else {
return mid;
}
}
public static void main(String[] args) {
int []arr= new int [100000000];
for(int i=0;i<arr.length;i++) {
arr[i]=i+1;
}
long before = System.currentTimeMillis();
// System.out.println(before+"ms");
int key=99999999;
int low=0;
int high=arr.length-1;
Search2(arr,low,high,key);
long now = System.currentTimeMillis();
System.out.println(" ******************二分法查找******************");
System.out.println("花费的时间为"+(now-before)+"ms");
int index= Search2(arr,low,high,key);
System.out.println("元素在数组中的位置为:"+(index+1));
System.out.println();
// for(int i=0;i<arr.length;i++) {
// System.out.print(arr[i]+" ");
//
// }
System.out.println("*********************顺序查找*********************");
long before1 = System.currentTimeMillis();
Search1(arr, key);
long now1 = System.currentTimeMillis();
System.out.println("花费的时间为"+(now1-before1)+"ms");
}
}
结果对比:
搞定收工!