学了没过多久又忘了,在这里写一下笔记。此处主要学习参考了labuladong写的二分查找笔记,也参考了别的优秀作品,加上了我自己的理解。
while(left<=right)
,左闭右开while(left<right)
。if(nums[mid] == target) right=mid;
if(nums[mid] == target) left=mid+1;
if(left==len) return 0;
目标元素比数组所有元素都大,返回-1if(left==0) return -1;
目标元素比数组所有元素都小,返回-1return nums[left] == target ? left : -1;
return nums[left-1] == target ? (left-1) : -1;
int search(vector<int>& nums, int target) {
int len=nums.size();
if(len == 0) return -1;
int left=0,right=nums[len-1];//闭区间
while(left<=right){//闭区间中不含元素的判定[left+1,left]
int mid=left+(right-left)/2;
if(nums[mid] == target){
return mid;//找到元素立即返回,找左右边界元素不是找到立即返回,而是继续缩小区间
}
else if(nums[mid] > target){
right=mid-1;//闭区间,从mid分割开
}
else if(nums[mid] < target){
left=mid+1;
}
}
return -1;//没有找到元素
}
下面是左闭右开区间
class Solution {
public:
int search(vector<int>& nums, int target) {
int len=nums.size();
if(len==0) return -1;
int left=0,right=len;
while(left < right){//左闭右开[left,right),结束条件left=right
int mid=left+(right-left)/2;
if(nums[mid] == target) return mid;
//中间值比目标值小,搜索区间[mid+1,right)
else if(nums[mid] < target) left=mid+1;
//中间值比目标值大,因为是右开取不到右节点,所以right更新为mid(取不到),搜索区间[left,mid)
else if(nums[mid] > target) right=mid;
}
return -1;
}
};
下面的两个代码我写的有点问题,部分可以成功返回下标,部分返回-1
这篇博客里面的找边界目标的代码运行正确。下面的可能是我哪里细节没写对
int left_bound(vector<int>& nums, int target){
int len=nums.size();
if (len == 0) return -1;
int left=0,right=len;
while(left < right){//因为右边界取不到索引
int mid=left+(right-left)/2;
if(nums[mid]==target){
right=mid;//缩小边界,不断向左边界靠近
}
else if(nums[mid]>target){
right=mid;
}
else if(nums[mid]<target){
left=mid+1;
}
//目标元素比数组中的所有元素都大
if(left==len) return -1;
//反之区间只有两个元素时,且刚好是两个相同的元素
return nums[left]==target ? left : -1;
}
}
int main(){
vector<int> nums;
nums.push_back(0);nums.push_back(1);nums.push_back(1);nums.push_back(2);nums.push_back(3);
int ans=left_bound(nums,4);
cout<<ans<<endl;
return 0;
}
int right_bound(vector<int>& nums,int target){
int len=nums.size();
if l(en == 0) return -1;
int left=0,right=len;
while(left < right){//因为右边界取不到索引
int mid=left+(right-left)/2;
if(nums[mid]==target){
//不断向右边界靠近
left=mid+1;
}
else if(nums[mid]>target){
right=mid;
}
else if(nums[mid]<target){
left=mid+1;
}
//没找到右边界
if(left==0) return -1;
//因为找到目标,左边界向有缩进,left=mid+1。当while结束时,nums[left]一定不等于target,而nums[left-1]有可能是
return nums[left -1] == target ? (left-1) : -1;
}
int main(){
vector<int> nums;
nums.push_back(0);nums.push_back(1);nums.push_back(1);nums.push_back(2);nums.push_back(3);
int ans=right_bound(nums,1);
cout<<ans<<endl;
}