2020.2.9
13:14
二分法
定義:假設數據是按升序排序的,對於給定值key,從序列的中間位置k開始比較,
如果當前位置arr[k]值等於key,則查找成功;
若key小於當前位置值arr[k],則在數列的前半段中查找,arr[low,mid-1];
若key大於當前位置值arr[k],則在數列的後半段中繼續查找arr[mid+1,high],
直到找到爲止,時間複雜度:O(log(n)) [3] 。
(前提:數組在查找前一定是已經排好序的)
傳統循環寫法:
//傳統的循環寫法
public class binarySearch {
public static int search(int[] arr, int key) {
int begin = 0; //高位
int end = arr.length - 1; //低位
while (begin <= end) {
int middle = (begin + end) / 2; //中間位
if (key < arr[middle]) { //查找的元素在左邊
end = middle - 1; //重新賦值高位
} else if (key > arr[middle]) { //查找的元素在右邊
begin = middle + 1; //重新賦值低位
} else {
return middle;
}
}
return -1; //沒有找到返回-1
}
遞歸寫法:
思路:全範圍內二分法查找
等價於三個子問題:
①左邊查找(遞歸)
②中間比
③右邊查找(遞歸)
(注意:左邊查找和右邊查找只能二選一,給人的感覺更像是一種多分支的遞歸,但是又是
一種單鏈的線性結構,線性結構有點類似於求階乘的樣子)
遞歸代碼:
//遞歸寫法
static int Search2(int []arr,int low,int high,int key) {
if(low>high) {
return -1;
}
int mid=low+((high+low)>>1); //利用移位來防止棧溢出,比較高效
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;
}
}
(一般情況下,遞歸的代碼寫出來十分的簡潔明瞭,但是,我怎麼感覺遞歸的代碼寫出來這麼複雜呢,比傳統的循環寫出來的代碼還要長)
附上兩種方法的比較完整代碼:
package LanQiaoKnowledgePractise;
//二分法查找元素
//傳統的循環寫法
public class binarySearch {
public static int search(int[] arr, int key) {
int begin = 0; //高位
int end = arr.length - 1; //低位
while (begin <= end) {
int middle = (begin + end) / 2; //中間位
if (key < arr[middle]) { //查找的元素在左邊
end = middle - 1; //重新賦值高位
} else if (key > arr[middle]) { //查找的元素在右邊
begin = middle + 1; //重新賦值低位
} else {
return middle;
}
}
return -1; //沒有找到返回-1
}
//遞歸寫法
static int Search2(int []arr,int low,int high,int key) {
if(low>high) {
return -1;
}
int mid=low+((high+low)>>1); //利用移位來防止棧溢出,比較高效
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={1,2,3,4,5,6};
System.out.println( search(arr ,5) );
System.out.println("*****************************");
System.out.println( Search2(arr,1,5,3) );
}
}
搞定收工!