二分查詢又稱為折半查詢,比如這裡有個1~100的隨機數,你來猜,一般人都會先猜50,如果這個隨機數比50小,下乙個就猜25,如果比25小,那在下乙個就是12或者13。反正無論如何我就猜他是這一堆數裡面的最中間的哪乙個。
這裡大家就會發現,二分查詢是有兩個條件的,一是數列有序,二是序列使用順序儲存結構(如陣列)。
最簡單也是最本質的二分查詢其實就是猜數字了,當然我這裡還可以舉個例子:現在這裡有公升序排列的10個數字,其中有個數字是5,求出5在這個序列中排第幾個?
先取10的一半即5,取第五位數字,看看這個數字比5大還是小,如果是大的話,因為是公升序排列,第五位之後的包括第五位數字都不可能是5,可以不去理會,所以現在這個要查詢的序列就變成了從第一位到第四位數字了。就這樣一直折半查詢,直到求出答案。
看到這裡,大家有些人會覺得直接遍歷不就好咯,但是折半查詢畢竟每次都把要查詢序列消減了一半,如果題目給出的是n個數字的話,那麼遍歷的時間複雜度是o(n),而二分查詢的時間複雜度是o(log2(n)),在n較大的情況下二分查詢無疑是比遍歷要快很多很多的(平均時間來看)。
題目給出n個已經公升序排列的數字,對於每次詢問(總共t次詢問),求出值為m的數字排在第幾位,如果沒有m這個數字,則輸出-1,主要**如下:
int n, t, s[100007];
scanf("%d %d", &n, &t);
for (int i = 0; i < n; i++)
scanf("%d", &s[i]);
for (int i = 0; i < t; i++)
if (s[mid] == m)
printf("%d\n", mid+1);
else
printf("-1\n");
}
想到二分查詢,我在想如果有一串沒有排序的數字,我要求值為m的數字在這堆數裡面排行第幾(即第幾大)。
我可以先用sort()
函式把這串數字快排一下,再用二分查詢來算m排行第幾。
當然快排其實感覺上和二分查詢其實有點類似,所以不如乾脆一邊快排一邊查詢,在快排中的每次將比mid大的分到一邊,比它小的分到另一邊,這時候只需比較mid是大於還是小於m,然後就可以把其中大的或者小的那一邊給捨去掉了。就這樣一直折半,直到mid == m
時,這時候mid排行老幾,m就排行老幾。
當然其實很多時候,比較難一點的二分查詢,它的形式一般都比較特別一點,但是本質上,都是有個max最大值,min最小值,mid中間值可以進行二分查詢演算法的,這個其實還不是很好講,因為每道題有每道題的變化,但是本質上的max,min,mid代表的查詢序列還是在的。
大家有興趣的可以看看這道題,其實不是很難,但是給我們看到了二分查詢是如何在題目**現。p1873 砍樹
這幾天其實都不是很想學習,在又不想學習,又不想打遊戲的情況下,我發現寫文章就可以一直寫下去的,也不會感覺很煩躁。就挺好的,嘿嘿。
本文使用 markdown.com.cn 排版
14 二分查詢
給定乙個排序的整數陣列 公升序 和乙個要查詢的整數target,用o logn 的時間查詢到target第一次出現的下標 從0開始 如果target不存在於陣列中,返回 1。樣例 在陣列 1,2,3,3,4,5,10 中二分查詢3,返回2。思路 1 target array mid 時,不能直接返回...
14 二分查詢
給定乙個排序的整數陣列 公升序 和乙個要查詢的整數target,用o logn 的時間查詢到target第一次出現的下標 從0開始 如果target不存在於陣列中,返回 1。樣例 在陣列 1,2,3,3,4,5,10 中二分查詢3,返回2。思路 定三個座標,頭座標,尾座標,中間座標,每次判斷要查詢的...
14 二分查詢
給定乙個排序的整數陣列 公升序 和乙個要查詢的整數target,用o logn 的時間查詢到target第一次出現的下標 從0開始 如果target不存在於陣列中,返回 1。在陣列 1,2,3,3,4,5,10 中二分查詢3,返回2。如果陣列中的整數個數超過了2 32,你的演算法是否會出錯?思路 剛...