目錄
一、什麼是二分查詢?
二、時間複雜度分析?
三、如何實現二分查詢?
四、使用條件(應用場景的侷限性)
五、思考
二分查詢針對的是乙個有序的資料集合,每次通過跟區間中間的元素對比,將待查詢的區間縮小為之前的一半,直到找到要查詢的元素,或者區間縮小為0。
1.時間複雜度
假設資料大小是n,每次查詢後資料都會縮小為原來的一半,最壞的情況下,直到查詢區間被縮小為空,才停止。所以,每次查詢的資料大小是:n,n/2,n/4,…,n/(2^k),…,這是乙個等比數列。當n/(2^k)=1時,k的值就是總共縮小的次數,也是查詢的總次數。而每次縮小操作只涉及兩個資料的大小比較,所以,經過k次區間縮小操作,時間複雜度就是o(k)。通過n/(2^k)=1,可求得k=log2n,所以時間複雜度是o(logn)。
2.認識o(logn)
①這是一種極其高效的時間複雜度,有時甚至比o(1)的演算法還要高效。為什麼?
②因為logn是乙個非常「恐怖「的數量級,即便n非常大,對應的logn也很小。比如n等於2的32次方,也就是42億,而logn才32。
③由此可見,o(logn)有時就是比o(1000),o(10000)快很多。
1.迴圈實現
**實現:
public int binarysearch1(int a, int val)
return -1;
}
注意事項:
①迴圈退出條件是:start<=end,而不是start②mid的取值,使用mid=start + (end - start) / 2,而不用mid=(start + end)/2,因為如果start和end比較大的話,求和可能會發生int型別的值超出最大範圍。為了把效能優化到極致,可以將除以2轉換成位運算,即start + ((end - start) >> 1),因為相比除法運算來說,計算機處理位運算要快得多。
③start和end的更新:start = mid - 1,end = mid + 1,若直接寫成start = mid,end=mid,就可能會發生死迴圈。
2.遞迴實現
public int binarysearch(int a, int val)
private int bsear(int a, int val, int start, int end)
1.二分查詢依賴的是順序表結構,即陣列。
2.二分查詢針對的是有序資料,因此只能用在插入、刪除操作不頻繁,一次排序多次查詢的場景中。
3.資料量太小不適合二分查詢,與直接遍歷相比效率提公升不明顯。但有乙個例外,就是資料之間的比較操作非常費時,比如陣列中儲存的都是長度超過300的字串,那這是還是儘量減少比較操作使用二分查詢吧。
4.資料量太大也不是適合用二分查詢,因為陣列需要連續的空間,若資料量太大,往往找不到儲存如此大規模資料的連續記憶體空間。
1.如何在1000萬個整數中快速查詢某個整數?
①1000萬個整數占用儲存空間為40mb,占用空間不大,所以可以全部載入到記憶體中進行處理;
②用乙個1000萬個元素的陣列儲存,然後使用快排進行公升序排序,時間複雜度為o(nlogn)
③在有序陣列中使用二分查詢演算法進行查詢,時間複雜度為o(logn)
2.如何程式設計實現「求乙個數的平方根」?要求精確到小數點後6位?
2 二分查詢(上)
二分模板有兩個,分別適用於不同的情況。演算法思路 假設目標值在閉區間 l,r 中,每次將區間長度縮小一半,當l r時,我們就找到了目標值。版本一 當我們將區間 l,r 劃分成 l,mid 和 mid 1,r 時,其更新操作時l mid 1或者 r mid 計算mid時不需要加1。版本二 當我們將區間...
演算法筆記 二分查詢(上)
5.總結 二分查詢針對的是乙個有序的資料集合,查詢思想有點類似分治思想。每次都通過跟區間的中間元素對比,將待查詢的區間縮小為之前的一半,直到找到要查詢的元素,或者區間被縮小為 0。二分查詢是目前為止遇到的第乙個時間複雜度為 o logn 的演算法。堆 二叉樹的操作等等,它們的時間複雜度也是 o lo...
資料結構和演算法之 二分查詢上
二分查詢 binary search 的思想非常簡單,但看似越簡單的東西往往越難掌握好,想要靈活運用就更加困難。生活中二分查詢的思想無處不在。乙個最常見的就是猜數遊戲,我隨機寫乙個 0 到 99 的數,然後你來猜我寫的是什麼。猜的過程中,我會告訴你每次是猜大了還是猜小了,直到猜中為止。假如我寫的數是...