1. 基本介紹
二分思想一般用於查找,見其名知其意,這是一個半半開的算法。第一次接觸二分思想的時候是高中的數學學習中,給定一個方程 f(x) = 0的根所在的區間,可以用根存在定理不斷二分區間,當區間長度小於給定的精度時,即可近似求出方程的解,當然也可以用來求平方根和立方根等。同樣,這種查找思想也可以運用於計算機內結構化數據的查找。(tips: 二分查找思想簡單,細節魔鬼)。(詳講博客推薦)
二分查找有很多應用,由於其時間復雜度很低,它可以暴力破解很大的數據。
- 核心思想
使用二分查找的前提:待查找序列必須有序(升序或降序,本文主要以升序為例)
確定查找區間(left, right),取區間中間值mid = (left + right)/2,比較中間值與左右兩邊的值,確定待查元素key所在區間,舍棄無效區間(mid = left 或mid = right)。

- 算法效率分析
時間復雜度:對於數據規模n,每次二分會使查找區間長度減半。最好情況只需要一次查找即可,最壞情況要找()次。綜上述,二分算法其漸進時間復雜度為O()。所以,很多地方考查找時卡時間復雜的時候就要考慮使用二分啦。
空間復雜度:沒有使用額外空間,比較友好。
- 代碼實現
- 朴素實現
int BinaryChop(int *arr, int len, int key) { int left = 0, right = len, mid; while (left < right) { mid = (left + right) / 2; if (arr[mid] == key) return mid; // 找到返回元素位置 else if (arr[mid] > key) right = mid - 1; else left = mid + 1; } return -1;// 沒找到返回-1 }
- 通用實現
int search(int k) { int l = -1,r = n;//注意的是數組是從0開始的 while(l + 1 < r) { int mid = l + r >> 1; if(a[mid] <= k) l = mid; else r = mid; } return r;//返回的是大於k的第一個位置 }
- C++中STL內的函數
lower_bound(begin, end, num):從數組的begin位置到end-1位置二分查找第一個大於等於num的數字,找到返回該數字的地址,不存在則返回end。通過返回的地址減去起始地址begin,得到找到數字在數組中的下標。
upper_bound(begin, end, num):從數組的begin位置到end-1位置二分查找第一個大於num的數字,找到返回該數字的地址,不存在則返回end。通過返回的地址減去起始地址begin,得到找到數字在數組中的下標。
- 習題鏈接
https://www.luogu.com.cn/problem/P2249 P2249 【深基13.例1】查找
https://www.luogu.com.cn/problem/P1102 P1102 A-B 數對
https://www.luogu.com.cn/problem/P1024 P1024 [NOIP2001提高組]一元三次方程求解
https://www.luogu.com.cn/problem/P1678 P1678 煩惱的高考志願
https://www.luogu.com.cn/problem/P2440 P2440 木材加工
http://120.78.128.11/Problem.jsp?pid=2145 二分法模板
http://120.78.128.11/Problem.jsp?pid=1762 杯子
http://120.78.128.11/Problem.jsp?pid=2366 二分強化——全面查詢
http://120.78.128.11/Problem.jsp?pid=2446 Champion_Q的魔法蛋糕
https://www.luogu.com.cn/problem/P2678 P2678 [NOIP2015 提高組] 跳石頭
https://www.luogu.com.cn/problem/P3853 P3853 [TJOI2007]路標設置
我的題解:
洛谷-P2249 【深基13.例1】查找 - Kirk~~ - 博客園 (cnblogs.com)
洛谷-P1102 A-B 數對 - Kirk~~ - 博客園 (cnblogs.com)
洛谷-P1024 [NOIP2001 提高組] 一元三次方程求解 - Kirk~~ - 博客園 (cnblogs.com)
