演算法基礎:
一、大O表示法:
指示演算法的速度有多快,用於指出隨數量的增大,演算法的所需步驟增加的速度,常見的大O執行時間(時間複雜度):
O(1)表示常數階時間複雜度
O(log n),也叫對數時間複雜度,這樣的演算法包括二分查詢。
O(n),也叫線性階時間複雜度,這樣的演算法包括簡單查詢。
O(n * log n), (n*對數複雜度)
O(n^2),平方階時間複雜度
O(n!),階乘階時間複雜度
複製程式碼
n越來越大時,演算法效率圖解:
要點
-
1.二分查詢法只適用於從有序的佇列中進行查詢(比如數字和字母等),將佇列排序後再進行查詢
-
2.二分查詢法的執行時間為對數時間O(㏒₂n) ,即查詢到需要的目標位置最多只需要㏒₂n步,假設從[0,99]的佇列(100個數,即n=100)中尋到目標數30,則需要查詢步數為㏒₂100 , 即最多需要查詢7次( 2^6 < 100 < 2^7)
-
3.簡單查詢(遍歷查詢)的執行時間為線性時間O(n), 假設從[0,99]的佇列中(n=100)尋到目標數30,則最多需要查詢步數為100步
-
4.對於容器內數量很少的情況下,2種查詢也許沒啥差別,當數量大的情況下,差別就很大,比如假設查詢比較步驟一次需要1秒,當容量數目為100000時,O(n)需要100000秒即約27.8小時,而logn只需要 2^16 < 100000 < 2^17,即17秒,這差距非常的大
-
5.時間複雜度都是針對最壞的情況所表示的,表示最多需要多少步
案例
從1~99的容器內,找出指定的數字;
java實現:
A:簡單查詢法,即遍歷查詢,全部遍歷直到找到指定的數便停止
/**
* 簡單查詢
* @param array 傳入存放全部資料的容器
* @param target 需要查詢的目標數
* @return
*/
public Integer search(Integer[] array,int target){
for(int i=0;i<array.length;i++){
if(array[i] == target){
return i;
}
}
return null;
}
B:二分查詢法
/**
* 二分查詢法
* @param array 傳入存放全部資料的容器
* @param target 需要查詢的目標數
* @return
*/
public Integer searchDichotomy(Integer[] array, int target){
int low =0;
int hight=array.length-1;
while(low<=hight){ //遍歷還沒結束
int mid = (low+hight)/2; //取中間值mid點位置
if(array[mid]==target){ //尋找到目標數
return mid;
}
if(array[mid] > target){ //如果中間值大於目標數,則將highr點位置移動mid位置左邊
hight = mid-1;
}
if(array[mid] < target){ //如果中間值小於目標數,則將low點位置移動mid位置右邊
low = mid+1;
}
}
return null;
}
複製程式碼
圖解:
假設容器中為[1,99],共99個數 必須明白因為時間複雜度是針對最壞情況的,二分查詢所需最多為7步,簡單遍歷法最多為99步(當查詢的是數99);
根據實際需要查詢的數,所消耗的步驟不一定一樣,但都不會超過時間複雜度
步驟圖解如下所示([1,99],即n=99,查詢的數為30):
時間複雜度推算過程:
參考:https://blog.csdn.net/frances_han/article/details/6458067 二分查詢的基本思想是將n個元素分成大致相等的兩部分,去a[n/2]與x做比較,如果x=a[n/2],則找到x,演算法中止;如果x<a[n/2],則只要在陣列a的左半部分繼續搜尋x,如果x>a[n/2],則只要在陣列a的右半部搜尋x. 時間複雜度無非就是while迴圈的次數! 總共有n個元素, 漸漸跟下去就是n,n/2,n/4,....n/2^k,其中k就是迴圈的次數 由於你n/2^k取整後>=1 即令n/2^k=1 可得k=log2n,(是以2為底,n的對數) 所以時間複雜度可以表示O()=O(logn)
有興趣共同進步可以掃描關注微信訂閱號