問題:給定已按公升序排好序的n個元素a[0:n-1],現要在這n個元素中找出一特定元素x,返回其(首次)出現的位置。
雖說是老問題,但是並不可簡單忽視,網上有人說「十個二分九個錯」,還是要好好梳理一下。
問題一,區間開閉
設查詢區間左右端點為left與right,這兩個點其實開閉均可,一般統一用閉合。
問題二,中位數
中位數有上位中位數和下位中位數之分,如序列1234上位中位數為2,下位中位數為1,此處的2和1均為下標。設序列長度為length,則有:
下位中位數lowermedian = (length-1)/2最常採用的是下位中位數。上位中位數uppermedian = length/2
在閉區間的前提下,中位數可以寫成:
median = left + (right - left)/2問題三,溢位
不要將中位數寫成:
median = (left + right)/2這樣寫有溢位的風險。
問題四,終結條件
不要用left==right作為終結條件,會被跳過。例如在序列[1,5]中尋找0,若終結條件為left==right,就會導致迴圈一直出不去。
正確的終結條件是:
left > right滿足終結條件後,直接返回-1即可。
問題五,遞推方向
若沒有重複元素,那麼根據median所對應的值大於、小於或者等於target,可以分別進行左移right,右移left和返回median操作。值得注意的是例如在左移right時,可以不僅僅將其設為median,而是設為median-1,可以減少一些計算。
若有重複元素,返回所查詢的元素第一次出現的位置,那麼我們可以從前面的沒有重複元素的思路考慮。考察left指標,只有在median對應的值小於target時,left才會右移,而median對應的值又大於等於left對應的值,那麼當target等於left對應的值時,left將不再右移。換言之left最終將停留在target第一次出現的位置,這正是我們想要的。對於right而言,同理將會停留在target最後一次出現的位置,最終返回的就是left和right的中位數。為了使其最終返回第一次出現的位置,那麼在median對應的值等於target的時候,繼續向左搜尋,即可最終到達left。
問題六,查詢元素不存在
假如查詢的元素不存在,演算法將會返回其按公升序排序應該插入的位置。如果想返回-1,需要在查詢過程中記錄是否找到了查詢的元素,以便進行區分。
//二分查詢指定元素target在序列a[0..n-1]中所在的位置
//無重複元素,遞迴實現
//輸入:乙個排序完成的序列a[0..n-1]以及其中的乙個元素target
//輸出:target在序列中所在的下標
int bs(int* a,int target,int n,int left,int right)
//二分查詢指定元素target在序列a[0..n-1]中所在的位置
//無重複元素,非遞迴實現
//輸入:乙個排序完成的序列a[0..n-1]以及其中的乙個元素target
//輸出:target在序列中所在的下標
int bs(int *a,int target,int n)
return -1;
}//二分查詢指定元素target在序列a[0..n-1]中所在的位置
//重複元素,遞迴實現,不考慮查詢元素不存在的情況
//輸入:乙個排序完成的序列a[0..n-1]以及其中的乙個元素target
//輸出:target在序列中所在的下標
int bs(int* a,int target,int n,int left,int right)
//二分查詢指定元素target在序列a[0..n-1]中所在的位置
//重複元素,非遞迴實現,查詢失敗返回-1
//輸入:乙個排序完成的序列a[0..n-1]以及其中的乙個元素target
//輸出:target在序列中所在的下標
int bs(int* a,int target,int n)
}if(***) return left;
else return -1;
}
問題輸入規模:序列長度n
基本操作:比較a[mid]和target
是否僅與問題輸入規模有關:否,需要考慮最好、最壞、平均
是否遞迴:二者複雜度一樣,分析遞迴
根據遞迴時間複雜度計算公式,a=1,b=2,f(n) = o(1),代入得最壞時間複雜度為:o(logn),最好時間複雜度為o(1)
分治法 二分查詢
1 首先二分查詢滿足分治法的四個條件 1 原問題的解可以通過分解為若干個小的問題來解決 將原陣列序列可分解為兩個子串行 2 小的問題的解決方法和原問題的解決方法大致相似 都是確定乙個序列的上界和下界然後求得mid進行比較 3 小問題的解可以通過合併從而得到原問題的解 在子串行中可以更容易得到解從而r...
分治法 二分查詢
問題描述 二分查詢又稱為折半查詢,它要求待查詢的資料元素必須是按關鍵字大小有序排列的。問題描述 給定已排好序的n個元素s1,sn,現要在這n個元素中找出一特定元素x。首先較容易想到使用順序查詢方法,逐個比較s1,sn,直至找出元素x或搜尋遍整個序列後確定x不在其中。顯然,該方法沒有很好地利用n個元素...
分治法 二分查詢
分治 分治法是將乙個規模為n的問題分解為k個規模較小的子問題。注意 這裡的子問題一定是相互獨立且與原問題相同。用遞迴的方法解這些子問題。然後將各子問題的解合併到原問題的解。二分查詢演算法是運用分治的典型例子 分治 二分查詢 給定已按公升序排好序的n個元素a 0 n 1 現要在這n個元素中找出一特定元...