二分模板一共有两个,分别适用于不同情况。
算法思路:假设目标值在闭区间[l, r]中, 每次将区间长度缩小一半,当l = r时,我们就找到了目标值。
* 其中mid需要在while内部进行更新
* 最小R,最大L , R来加,L来减,无脑返L没问题
* L需要 long mid = (l + r + 1ll) >> 1
C++ 代码模板:
// 整数二分算法模板
bool check(int x) {/* ... */} // 检查x是否满足某种性质
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid; // check()判断mid是否满足当前条件最小值性质
else l = mid + 1;
}
return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid; // check()判断mid是否满足当前条件最大值性质
else r = mid - 1;
}
return l;
}
思路:使用二分法,因为是向下取整,即满足向下取整的最大性质
class Solution {
public:
int mySqrt(int x) {
int l = 0, r = x;
while(l < r)
{
long mid = (l + r + 1ll) >> 1;
if(mid * mid <= x) l = mid;
else r = mid - 1;
}
return l;
}
};
思路:使用两段二分
class Solution {
public:
int search(vector<int>& nums, int target) {
if (nums.empty()) return -1;
int l = 0, r = nums.size() - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (nums[mid] >= nums[0]) l = mid;
else r = mid - 1;
}
if (target >= nums[0]) l = 0;
else l = r + 1, r = nums.size() - 1;
while (l < r) {
int mid = l + r >> 1;
if (nums[mid] >= target) r = mid;
else l = mid + 1;
}
if (nums[r] == target) return r;
return -1;
}
};
解题思路:使用二分法,二分出左右区间两个满足的位置,然后返回结果
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)
{
int mid = (l + r) >> 1;
if(nums[mid]>=target)r = mid;
else l = mid + 1;
}
if(nums[r] != target) return{-1,-1};
int start = r;
l = 0,r = nums.size() - 1;
while(l < r)
{
int mid = (l + r + 1) >> 1 ;
if(nums[mid] <= target) l = mid;
else r = mid - 1;
}
int end = r;
return {start , end};
}
};
解题思路:二分,找到寻找满足性质的最小部分。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
if(nums.empty())return 0;
int l = 0, r = nums.size();
while(l < r)
{
int mid = l + r >> 1;
//需要找到的x和target的关系是x是>=target右侧最小的一个
if(nums[mid]>=target)r = mid;
else l = mid + 1;
}
return l;
}
};