二分查詢演算法詳解

2022-03-20 04:34:18 字數 2453 閱讀 5130

最近刷了很多二分查詢相關的題目,這裡將近期的收穫做乙個總結,包括二分查詢的變形問題。如果能掌握,我相信以後基本上二分查詢相關的問題對你來說,都不是問題。

二分查詢是啥我想不用過多的說明。我們都知道二分查詢的時間複雜程度是o(logn)。

o(logn) 查詢速度有多快呢?我們來分析一下。

我們假設資料大小是 n,每次查詢後資料都會縮小為原來的一半,也就是會除以 2。最壞情況下,直到查詢區間被縮小為空,才停止。

就因為這種特性,有的時候甚至比時間複雜度是常量級 o(1) 的演算法還要高效。為什麼這麼說呢?

因為 logn 是乙個非常「恐怖」的數量級,即便 n 非常非常大,對應的 logn 也很小。比如 n 等於 2 的 32 次方,這個數很大了吧?大約是 42 億。也就是說,如果我們在 42 億個資料中用二分查詢乙個資料,最多需要比較 32 次。

簡單的二分查詢我想大家應該都寫過。但是想一次將二分查詢寫對估計10個人裡面只有1個人能做到。下面給出題目和**,我們具體來分析一下。

題目:在有序的陣列a裡,找到某個指定的資料value。
public int bsearch(int a, int value)  else if (a[mid] < value)  else 

} return -1;

}

上訴**可以作為乙個二分查詢的模板**,我相信你能輕易的看懂這段**。這裡需要強調幾個容易出錯的地方:

1.迴圈退出條件:

注意是low<=high,而不是 low

2.mid 的取值:

實際上,mid=(low+high)/2 這種寫法是有問題的。因為如果 low 和 high 比較大的話,兩者之和就有可能會溢位。改進的方法是將 mid 的計算方式寫成low+(high-low)/2。更進一步,如果要將效能優化到極致的話,我們可以將這裡的除以 2 操作轉化成位運算 low+((high-low)>>1)。因為相比除法運算來說,計算機處理位運算要快得多。

3.low 和 high 的更新

low=mid+1,high=mid-1。注意這裡的 +1 和 -1,如果直接寫成 low=mid 或者 high=mid,就可能會發生死迴圈。比如,當 high=3,low=3 時,如果 a[3]不等於 value,就會導致一直迴圈不退出。

上面這種簡單的二分查詢大家基本上都會寫,需要注意的就是幾個容易出錯的地方。爭取這種簡單的二分查詢都是一次性通過。

我們平常很少會寫這種簡單的二分查詢,這裡我給出幾種常見的變形的二分查詢演算法。我們來觀察其通用性,掌握其技巧。

1. 題目:查詢第乙個值等於給定值的元素

例子:a:[1,3,4,5,6,,6,6,7,8],value:6。那麼需要定位到下標為4的元素

public int bsearch(int a, int value)  else if (a[mid] < value)  else 

} return -1;

}

仔細看看上訴演算法中,與之前的簡單的二分查區別在**?

我們來分析一下。首先我們還是按照簡單的二分查詢來算。當找到指定值的時候我們不能直接放回結果。需要再判斷一下,左邊的元素與自身是否相同。不相同則返回結果。否則繼續二分。

2. 題目:查詢第乙個大於等於給定值的元素

例子:a:[3,4,6,7,10] 如果查詢第乙個大於等於5的元素,那就是6

public int bsearch(int a, int value)  else 

} return -1;

}

如果 a[mid]小於要查詢的值 value,那要查詢的值肯定在[mid+1, high]之間,所以,我們更新 low=mid+1。

對於 a[mid]大於等於給定值 value 的情況,我們要先看下這個 a[mid]是不是我們要找的第乙個值大於等於給定值的元素。

如果 a[mid]前面已經沒有元素,或者前面乙個元素小於要查詢的值 value,那 a[mid]就是我們要找的元素。這段邏輯對應的**是第 7 行。

如果 a[mid-1]也大於等於要查詢的值 value,那說明要查詢的元素在[low, mid-1]之間,所以,我們將 high 更新為 mid-1。

要想寫好二分查詢,首先我們必須保證充分理解最簡單的二分查詢演算法。不熟悉的話多寫幾遍。

當遇到變形的二分查詢。我們需要改動簡單的二分查詢**。改動的點就在a[mid]與value的對比上加上相應的條件。

上面的兩道變形的演算法如果你多做幾遍一定會有自己的體會。

最後,需要特別主義的還是那三個特別容易出錯的地方:

1.迴圈退出條件:

2.mid 的取值:

3.low 和 high 的更新

詳解二分查詢演算法

二分查詢是通過將遞增序列不斷減半的方式尋找目標值的下標。其看似簡單,但往往存在一些細節被忽略,即while迴圈判斷條件和區間右邊界的取值方式。另外,我們往往只知二分查詢搜尋目標值的功能,而忽略了二分查詢的另外乙個功能,即尋找最大的小於目標值的元素和最小的大於目標值的元素。目錄 一 二分查詢演算法的基...

二分查詢演算法詳解

二分查詢針對的是乙個有序的資料集合,查詢思想有點類似分治思想。每次都通過跟區間的中間元素對比,將待查詢的區間縮小為之前的一半,直到找到要查詢的元素,或者區間被縮小為 0。二分查詢是一種非常高效的查詢演算法,高效到什麼程度呢?我們來分析一下它的時間複雜度。我們假設資料大小是 n,每次查詢後資料都會縮小...

二分查詢詳解

演算法概括 二分查詢又稱折半查詢,優點是比較次數少,查詢速度快,平均效能好 其缺點是要求待查表為有序表,且插入刪除困難。因此,折半查詢方法適用於不經常變動而查詢頻繁的有序列表。首先,假設表中元素是按公升序排列,將表中間位置記錄的關鍵字與查詢關鍵字比較,如果兩者相等,則查詢成功 否則利用中間位置記錄將...