引言
该方法来自b站算法大师兄,可用作通用模版处理二分查找问题,不用特意考虑边界临界值等情况。
方法描述
红色节点是小于target,绿色节点是大于等于target。
我们首先定义两个下标代表左和右,分别为-1和n。然后用红箭头和绿箭头分别指向这两个位置,然后计算中点用(left+right)/2,注意这里需要向下取整。然后判断中点位置是否是大于等于target,如果是我们就让它变为绿色,然后绿色箭头指向中点。如果不是,就把它变成红色让红色箭头指向它。如此循环知道left+1<right为止。
例题
leetcode35.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left=-1,right=nums.size();
while(left+1<right)
{
int mid=(left+right)/2;
auto lfunc=[&](){
return nums[mid]>=target;
};
if(lfunc())
right=mid;
else
left=mid;
}
return right;
}
};
我们把判断是否是绿色节点设置成了lambda表达式形式,最后返回的值是第一个绿色节点的值。
如果找不到则该值肯定是等于n的,正好是插入位置,如果找得到,该值正好是第一个绿色节点下标即要查找的值。
leetcode.704.二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
class Solution {
public:
int binary_search(vector<int> nums,int target)
{
int l=-1,r=nums.size();
while(l+1<r)
{
int mid=(r+l)/2;
if([&](){
return nums[mid]>=target;
}())
r=mid;
else
l=mid;
}
return r;
}
int search(vector<int>& nums, int target) {
int idx=binary_search(nums,target);
if(idx==nums.size()||nums[idx]!=target)
return -1;
return idx;
}
};
这里我们干脆对二分进行了封装,最后返回的idx值是二分查找的下标,如果查找的元素大于所有元素,则返回n,否则返回第一个绿色节点的值,然后判断这个位置的值是否等于target,如果不等于则返回-1,否则返回idx。
leetcode34.在排序数组中查找元素的第一个和最后一个位置
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
class Solution {
public:
int binary_search(vector<int>& nums,int target)
{
int left=-1,right=nums.size();
while(left+1<right)
{
int mid=(left+right)/2;
if([&](){
return nums[mid]>=target;
}())
right=mid;
else
left=mid;
}
return right;
}
vector<int> searchRange(vector<int>& nums, int target) {
int index=binary_search(nums,target);
if(nums.size()==index||nums[index]!=target)
return {-1,-1};
int index2=binary_search(nums,target+1);
return {index,index2-1};
}
};
这里我们采用的思路是先查找target元素找出如果找不到则返回-1,如果找到则是找到target出现的第一个元素。然后查找target+1出现的第一个位置。然后返回即可。
总结
该方法提供了一种模版供解决二分查找问题,以此记录方便复习。