int bsearch_1(int l, int r){
while (l < r){
int mid = (l + r) >> 1; // mid = l + ((r-l) >> 1)
if (check(mid)) r = mid; // check()判断mid是否满足性质
else l = mid + 1;
}
return l;
}
int bsearch_2(int l, int r){
while (l < r) {
int mid = (l + r + 1) >> 1; // 必须 + 1, 若溢出 改为long long
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
输入 / 输出样例
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
---------------------
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]
---------------------
输入:nums = [2,2], target = 3
输出:[-1,-1]
C++ 代码如下:
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if(nums.empty()) return {-1, -1};
int l = 0, r = nums.size() - 1;
// 模板一
while(l < r){ // 找 >= x 的第一个数 ——————> 用模板一
int mid = (l + r) / 2;
if(nums[mid] >= target) r = mid;
else l = mid + 1;
}
if(nums[l] != target) return {-1, -1}; // 没找到
int start = l;
// 模板二
l = 0, r = nums.size() - 1;
while(l < r){ // 找 <= x 的最后一个数 ——————> 用模板二
int mid = l + r + 1 >> 1;
if(nums[mid] <= target) l = mid;
else r = mid - 1;
}
int end = r;
return {start, end};
}
};
int start = lower_bound(nums.begin(), nums.end(), target) - nums.begin();
int end = upper_bound(nums.begin(), nums.end(), target) - nums.begin() - 1
完整代码如下
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if(nums.empty()) return {-1, -1};
int start = lower_bound(nums.begin(), nums.end(), target) - nums.begin();
if(start >= nums.size()) return {-1, -1}; // 没找到
int end = upper_bound(nums.begin(), nums.end(), target) - nums.begin() - 1;
if(end < start) return {-1, -1};
// 特殊判断。因为upper和lower都是 > x, end是-1得到的
// 如[5,7,7,8,8,10]找6
// start = 1
// end = 0
return {start, end};
}
};
输入 / 输出样例
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 11
输出:true
代码
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.empty() || matrix[0].empty()) return false;
int n = matrix.size(), m = matrix[0].size();
int l = 0, r = m * n - 1; // 将数组展开为序列
while(l < r){
int mid = l + r >> 1;
if(matrix[mid / m][mid % m] >= target) r = mid;
// 二维坐标 转 一维坐标
// i = k / col
// j = k % col
else l = mid + 1;
}
if(matrix[l/m][l%m] != target) return false; // 没找到
return true;
}
};
输入 / 输出样例
输入:nums = [4,5,6,7,0,1,2]
输出:0
class Solution {
public:
int findMin(vector<int>& nums) {
int l = 0, r = nums.size()-1;
while(l < r){
int mid = (l + r)/2;
if(nums[mid] <= nums.back()) // 小于等于末尾
r = mid;
else l = mid + 1;
}
return nums[l];
}
};
输入 / 输出样例
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
----------------
输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1
代码
class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.empty()) return -1;
// 找min
int l = 0, r = nums.size() - 1;
while(l < r){
int mid = l + r >> 1;
if(nums[mid] <= nums.back()) r = mid;
else l = mid + 1;
} // 当前l, r都是min的下标
if(target <= nums.back()){ // 则在右区间进行二分查找
r = nums.size() - 1; // l = l
}// 否则在左区间进行二分查找
else l = 0, r--; // r = l - 1 = r--
while(l < r){
int mid = l + r >> 1;
if(nums[mid] >= target) r = mid;
else l = mid + 1;
}
if(nums[l] != target) return -1;
return l;
}
};
输入 / 输出样例
输入:nums = [1,2,1,3,5,6,4]
输出:1 或 5
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int l = 0, r = nums.size() - 1;
while(l < r){
int mid = l + r >> 1;
if(nums[mid] > nums[mid+1]) r = mid;
else l = mid + 1;
}
return l;
}
};
输入 / 输出样例
输入:nums = [3,1,3,4,2]
输出:3
代码
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int l = 1, r = nums.size()-1;
while(l < r){
int mid = (l + r) / 2;
int cnt = 0;
for(auto i : nums){
if(i >= l && i <= mid) cnt ++;
}
if(cnt > mid - l + 1) r = mid; // cnt > 左区间元素个数,则从左区间找
else l = mid + 1;
}
return l;
}
};
输入 / 输出样例
输入:citations = [0,1,3,5,6]
输出:3
代码
class Solution {
public:
int hIndex(vector<int>& c) {
int n = c.size();
int l = 0, r = n; // h的大小一定不超过数组长度
while(l < r){
int mid = (l+r+1)/2;
if(c[n - mid] >= mid) l = mid;
else r = mid - 1;
}
return l;
}
};