關於二分查詢

2021-08-25 12:06:19 字數 4191 閱讀 1916

在電腦科學中,二分搜尋(英語:binary search),也稱折半搜尋(英語:half-interval search)[1]、對數搜尋(英語:logarithmic search)[2],是一種在有序陣列中查詢某一特定元素的搜尋演算法。搜尋過程從陣列的中間元素開始,如果中間元素正好是要查詢的元素,則搜尋過程結束;如果某一特定元素大於或者小於中間元素,則在陣列大於或小於中間元素的那一半中查詢,而且跟開始一樣從中間元素開始比較。如果在某一步驟陣列為空,則代表找不到。這種搜尋演算法每一次比較都使搜尋範圍縮小一半。

二分演算法作為演算法考試和面試中的重點,因此對此做了一些總結。

關於二分演算法的一些基本操作

1.給定乙個有序(非降序)陣列a,求任意乙個i使得a[i]等於target,不存在則返回-1

//最樸素的二分查詢。基礎中的基礎

int search(int a, int n, int target)

return -1;

}

2.給定乙個有序(非降序)陣列a,可含有重複元素,求最小的i使得a[i]等於target,不存在則返回-1 。

int searchfirstpos(int a, int n, int target)  

/*

迴圈過程中,當low大於0時,a[low-1]是小於target的,因為a[mid] < target時,

low=mid+1;當high小於n-1時,a[high]是大於等於target的,因為a[mid] >= target時,

high = mid;迴圈結束時,low 等於 high,所以,如果a[low](a[high])等於target,

那麼low(high)就是target出現的最小位置,否則target在陣列中不存在。

*/

if(a[low] != target)

return -1;

else

return low;

}

3.給定乙個有序(非降序)陣列a,可含有重複元素,求最大的i使得a[i]等於target,不存在則返回-1

int searchlastpos(int a, int n, int target)  

/*

迴圈過程中,當high小於n-1時,a[high+1]是大於target的,因為a[mid] > target時,

high=mid-1;當low大於0時,a[low]是小於等於target的,因為a[mid] <= target時,

low = mid;迴圈結束時,low 等於 high,所以,如果a[high](a[low])等於target,

那麼high(low)就是target出現的最大位置,否則target在陣列中不存在。

*/

if(a[high] != target)

return -1;

else

return high;

}

4.給定乙個有序(非降序)陣列a,可含有重複元素,求最大的i使得a[i]小於target,不存在則返回-1。

int searchlastposlessthan(int a, int n, int target)  

/*

迴圈過程中,當low大於0時,a[low]是小於target的,因為a[mid] < target時,

low=mid;當high小於n-1時,a[high+1]是大於等於target的,因為a[mid] >= target時,

high = mid-1;迴圈結束時,low 等於 high,所以,如果a[low](a[high])小於target,

那麼low(high)就是要找的位置,否則不存在這樣的位置(a[0] >= target時)。

*/

return a[low] < target ? low : -1;

}

5.給定乙個有序(非降序)陣列a,可含有重複元素,求最小的i使得a[i]大於target,不存在則返回-1。

int searchfirstposgreaterthan(int a, int n, int target)  

/*

迴圈過程中,當low大於0時,a[low-1]是小於等於target的,因為a[mid] <= target時,

low=mid+1;當high小於n-1時,a[high]是大於target的,因為a[mid] > target時,

high = mid;迴圈結束時,low 等於 high,所以,如果a[high](a[low])大於target,

那麼high(low)就是要找的位置,否則不存在這樣的位置(a[n-1] <= target時)。

*/

return a[high] > target ? high : -1;

}

有一些規律可以幫助記憶,不用臨時想很多。要求最小的xx,就用

low = mid + 1; high = mid;
要是求最大的xx,就用

low = mid + 1; high = mid - 1; 而且 mid = low + ((high - low + 1) >> 1)
做幾個題目拓展一下。

1.leetcode-74 搜尋二維矩陣

tips:這題其實是二分查詢的乙個小變形,平常的二分查詢是在一維陣列中進行的,而這次實在二維陣列中,可以把它看成乙個一維陣列。

bool searchmatrix(vector>& matrix, int target) 

else if(matrix[mid/n][mid%n] > target)

else

} return false;

} }

2.leetcode-69 x的平方根

tips:這題說白了就是上面的找最大小於某個數的那種方法。從1到x挨個去嘗試即可。

int mysqrt(int x)  else 

}}

3.leetcode-50 pow(n,x)

tips:這題運用了類似二分查詢的方法,考察靈活運用。

double mypow(double x, int n) 

double res = mypow(x, n/2);

if(n % 2 == 0 && !isinf(res*res))

return res*res;

else if(n % 2 == 1 && !isinf(res*res*x))

return x*res*res;

else return 0.0;

}

4.leetcode-35 搜尋插入位置

tips:可以轉換為 找最小的大於等於target問題。

public:

int searchinsert(vector& nums, int target)

return low ;

}

5.leetcode-33 搜尋旋轉排序陣列

tips:見注釋

int search(vector& nums, int target) 

int rot = low;

low = 0; high = nums.size()-1;

while(low <= high)

return -1;

}

leetcode-29 兩數相乘

tips:類似二分法的嘗試性演算法。

int divide(int dividend, int divisor) 

*** -= temp;

res += multiple;

}return sign == 1 ? res : -res;

}

關於二分查詢

面試過很多人,對於初級程式設計師來說,我一般會給他簡單的已經比較成熟的演算法來考察他,一來來他對既有演算法的熟悉度,二來考察他對於一般程式設計問題的邏輯思維能力,二分查詢是有序數列中查詢的常用演算法,也是比較容易實現的查詢演算法之一,這個是stl的實現 template randomaccessit...

關於二分查詢

一 關於二分查詢 1.查詢目標值 當right nums.size 1時,判定條件應該為left right right賦值時也應該是mid 1 當right nums.size 時,判定條件應該為left 目標值的數 int search vector nums,int target return...

關於二分查詢

luogu 1571 眼紅的medusa 二分模版題 include using namespace std int n,m,x,l,r,mid,cnt,a 110000 b 110000 c 110000 intmain if x b l cnt c cnt x for int i 1 i cou...