二分搜尋及其擴充套件

2021-09-06 08:27:13 字數 2062 閱讀 4353

二分搜尋

折半搜尋,也稱二分查詢演算法、二分搜尋,是一種在有序陣列中查詢某一特定元素的搜尋演算法。搜素過程從陣列的中間元素開始,如果中間元素正好是要查詢的元素,則搜素過程結束;如果某一特定元素大於或者小於中間元素,則在陣列大於或小於中間元素的那一半中查詢,而且跟開始一樣從中間元素開始比較。如果在某一步驟陣列為空,則代表找不到。這種搜尋演算法每一次比較都使搜尋範圍縮小一半。

時間複雜度:二分搜尋每次把搜尋區域減少一半,很明顯時間複雜度為o(logn)。 

空間複雜度:o(1),雖以遞迴形式定義,但是尾遞迴,可改寫為迴圈。

二分搜尋的基本實現

二分查詢法在演算法家族大類中屬於「分治法」,分治法基本都可以用遞迴來實現的,二分查詢法的遞迴實現如下:

int binary_search(int array, int low, int high, int

target)

非遞迴實現:

int binary_search(int arr,int n ,int

key)else

} return -1;//

沒有找到元素,返回-1

}

關於二分搜尋,想起之前看過的一道題目:乙個陣列是由乙個遞減數列經過若干次左移形成的,例如是由陣列 經過兩次左移形成的,在這種陣列中查詢某乙個數。函式原型是 int search(int a,int low,int high,int k);

陣列的形態如圖所示:

仔細想想,如果取中間元素對陣列進行劃分的話,那麼陣列可以分為兩個部分,陣列的兩個部分不外乎三種情況:

有序  mid  有序

部分有序  mid  有序

有序   mid  部分有序

這樣遞迴下去,用二分查詢的一種變形,一樣可以查詢出。**如下:

int bsearch(int a, int n, int

key)

else

} else

else

} }

return -1

; }

搜狗還有一道面試題目:

有乙個陣列,該陣列的特點是:前一部分遞增有序,後一部分遞減有序,求陣列的峰值位置。

我們發現,給出的陣列可能有如下三種形態:

其中後兩種情況是屬於特殊的,是有序陣列,峰值的位置就是陣列的開始或結束索引。我們單單考慮第一種情況。

思考1:線性掃瞄,思路最簡單,也最容易實現,只需掃瞄 一遍陣列,比較當前元素與前乙個元素的大小關係,一旦碰到當前元素比前一元素小,前一元素就是峰值。或者比較當前元素與後一元素,一旦後一元素比當前元素小,當前元素就是峰值。此方法的缺點是需要線性時間o(n)

思考2:考慮二分搜尋,如果不考慮情況2和情況3.對於情況一而言,mid中間元素的位置不外乎三個情況:

是不是跟二分搜尋很類似?

我們可以根據中間元素與兩邊元素的大小關係,判斷搜尋左邊還是右邊。據此,不難寫出如下**(未經嚴格測試):

#include //

陣列是先增後減陣列。

int findmax(int *a ,int

n)else

if(a[mid] >= a[mid-1] && a[mid] <=a[mid + 1

])else

}else

if((mid+1) <=high)

else

}else

else

} }

}

intmain();

printf(

"%d \n

",findmax(a,8

));

}

二分搜尋及其擴充套件

二分搜尋需要注意開閉區間的問題,限制條件和邊界要保持配對 low high low mid 1 high mid 1。二分搜尋的模板如下 cpp view plain copy 二分搜尋 intbinarysearch int num,intkey,intlow,inthigh return low...

二分搜尋以及其擴充套件形式

歡迎 如有錯誤敬請指正 二分搜尋使用的前提是陣列必須有序,在本文中,我們用lo low 表示查詢範圍的起始下標,hi hight 表示查詢範圍的結束下標,mid表示lo和hi的中間位置。1.一般情況二分搜尋 普通二分搜尋,如果找到key,返回任意乙個和key相等的元素下標,否則返回 1 public...

二分搜尋及其擴充套件(迴圈遞增陣列的搜尋)

二分搜尋需要注意開閉區間的問題,限制條件和邊界要保持配對 low high low mid 1 high mid 1。二分搜尋的模板如下 cpp view plain copy 二分搜尋 intbinarysearch int num,intkey,intlow,inthigh return low...