二分搜尋法 (Binary Search) 是一種在有序序列中高效搜尋的演算法。
透過不斷將搜尋範圍減半,時間複雜度只有 O(log n)。
適用條件:
C++ 提供內建二分搜尋工具:
函式 | 功能 | 回傳值 |
---|---|---|
binary_search |
是否存在 target | bool |
lower_bound |
第一個 ≥ target 的位置 | iterator |
upper_bound |
第一個 > target 的位置 | iterator |
範例:
vector<int> nums = {1, 2, 4, 4, 5, 7};
int target = 4;
auto lb = lower_bound(nums.begin(), nums.end(), target);
auto ub = upper_bound(nums.begin(), nums.end(), target);
cout << lb - nums.begin(); // 2
cout << ub - nums.begin(); // 4
原題:
https://cses.fi/problemset/task/1090
題意:
n 個小孩,每個小孩體重 w[i]
每個摩天輪車廂最多坐 2 個人,且總重量 ≤ x
求最少需要幾個車廂
解題思路:
將 w 排序
left 指向最輕的人
right 指向最重的人
如果 w[left] + w[right] <= x :一起做
否則最重的人單獨坐
每次使用一個車廂 → ans++
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,maxWeight;
cin>>n>>maxWeight;
vector<int> weight(n);
for(int i=0;i<n;i++){
cin>>weight[i];
}
sort(weight.begin(),weight.end());
int ferris=0;
int i=0,j=n-1;
while(i<=j){
if(weight[i]+weight[j]<=maxWeight){
++i,--j; //輕重可以一起坐
}
else --j; //重的自己一台
ferris++;
}
cout<<ferris<<endl;
return 0;
}
時間複雜度分析:O(n log n)
原題:
https://cses.fi/problemset/task/1091
題意:
有 n 張演唱會門票,每張價格 h[i]
有 m 個顧客,每位顧客最多只願意付 t[i]
每位顧客希望買到「價格 ≤ t[i] 且最接近 t[i]」的票
如果沒有符合的票,輸出 -1
解題思路:
將票價 h 排序
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
multiset<int> tickets;
for (int i = 0; i < n; i++) {
int x; cin >> x;
tickets.insert(x);
}
for (int i = 0; i < m; i++) {
int t; cin >> t;
auto it = tickets.upper_bound(t);
if (it == tickets.begin()) {
cout << -1 << endl;
} else {
--it;
cout << *it << endl;
tickets.erase(it);
}
}
}
原題:
https://leetcode.com/problems/binary-search/description/
題意:
給一個升序整數陣列 nums 和 target
找出 target 的索引
若不存在,回傳 -1
解題思路:
二分搜尋
每次計算中點 mid
比較 nums[mid] 與 target
更新搜尋範圍直到找到或區間為空
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0,right=nums.size()-1;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]==target) return mid;
else if(nums[mid]<target) left=mid+1;
else right=mid-1;
}
return -1;
}
};
原題:
https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/description/
題意:
在升序陣列 nums 中,找出目標值 target 的起始索引與結束索引
如果不存在,回傳 [-1, -1]
解題思路:
使用 lower_bound 找到第一個 ≥ target 的位置
使用 upper_bound 找到第一個 > target 的位置
如果 lower_bound 超出邊界或值不等於 target → 回傳 [-1, -1]
否則答案是 [lb, ub-1]
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
auto lb = lower_bound(nums.begin(), nums.end(), target);
auto ub = upper_bound(nums.begin(), nums.end(), target);
if (lb == nums.end() || *lb != target) return {-1, -1};
return {int(lb - nums.begin()), int(ub - nums.begin() - 1)};
}
};