2024年C C++最新【二分查找】有这一篇足够了(1),C C++开发基础课程

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

        }else if(nums[mid] < target){
            left = mid + 1;
    //target在右区间,所以[mid+1,right]
        }else{
    //(nums[mid]>target)target在左区间,所以[left,mid-1]
            right = mid - 1;
        }
    }
    return -1;
}

}


**第二种写法**



> 
> **定义 target 在一个在左闭右开的区间里,也就是[left, right) 这个中,**
> 
> 
> **根据二分法的边界处理方式,就有不同的考虑**。
> 
> 
> 因为定义在了这个区间中,所以考虑下面两点
> 
> 
> 
> **循环while结束的条件是什么**
> 
> 
> while (left < right) 要使用 <,因为left == right在区间[left, right)是没有意义的
> 
> 
> **给left和right赋什么值**
> 
> 
> if (nums[mid] > target) right 更新为 mid,因为当前nums[mid]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为mid,即:下一个查询区间不会去比较nums[mid]
> 
> 
> 


注意看和第一种方法中的图有什么不一样


![](https://img-blog.csdnimg.cn/2819c685f2e54e64afdc048f98bb70c0.png)



class Solution {
public:
int search(vector& nums, int target) {
int left = 0;
int right = nums.size();
// 定义target在左闭右开的区间里,即:[left, right)
while (left < right) {
//因为left==right的时候,在[left, right)是无效的空间,所以使用<
int mid = left + ((right - left) >> 1);
if (nums[mid] > target) {
right = mid;
// target 在左区间,在[left, mid)中
} else if (nums[mid] < target) {
left = mid + 1;
// target 在右区间,在[mid + 1, right)中
} else { // nums[mid] == target
return mid;
}
}
// 未找到目标值
return -1;




---



### 2.2 第一个错误的版本


链接  [278. 第一个错误的版本 - 力扣(LeetCode)](https://bbs.csdn.net/topics/618668825)


![](https://img-blog.csdnimg.cn/9be36f4b3bc2404880735ceddd2fb3b7.png)


分析一下


![](https://img-blog.csdnimg.cn/b2925dbcc80c46439a234c7eabe0a8e5.png)



/* The isBadVersion API is defined in the parent class VersionControl.
boolean isBadVersion(int version); */

public class Solution extends VersionControl {
public int firstBadVersion(int n) {

    int left = 1, right = n;
    while(left < right){
        int mid = left + (right - left) / 2;
        if(isBadVersion(mid)){
            right = mid ;
        }else{
            left = mid + 1;
        }
    }
    return right;
}

}




---



###  2.3 搜索插入位置


链接  [35. 搜索插入位置 - 力扣(LeetCode)](https://bbs.csdn.net/topics/618668825)


![](https://img-blog.csdnimg.cn/446b8c2bdcfd4e22a32922f57d3386d7.png)


 分析一下


![](https://img-blog.csdnimg.cn/66481f6aebe94376879ad55f21cf0761.png)


 ![](https://img-blog.csdnimg.cn/3629699ac04a41b68501580729f89991.png)



class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length-1;
while(left<=right){
int mid = left + (right - left)/2;
if(nums[mid] > target){
right = mid - 1;
}else if(nums[mid] < target){
left = mid + 1;
}else{
return mid;
}
}
return right+1;
}
}




---



###  2.4 在排序数组中查找元素第一个和最后一个位置


链接   [34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)](https://bbs.csdn.net/topics/618668825)


![](https://img-blog.csdnimg.cn/c8294b8905984fb3b7baba46f614b7aa.png)


 ![](https://img-blog.csdnimg.cn/50fcbc79949046ce83a0925d8c7fa3ba.png)


 这个题我们就可以使用二分查找来找它的左右边界


为了便于理解,我们寻找左右边界,分为两个二分查找写左右边界


**找左边界**



public int getLeftBorder(int[] nums, int target){
    int left = 0;
    int right = nums.length - 1;
    int leftBorder = -2;//用来记录leftBorder没有被赋值的情况
    while(left <= right){
        int mid = left + (right - left);
            if(nums[mid] >= target){
            //寻找左边界
                right = mid - 1;
                leftBorder = right;
            }else{
                left = mid + 1;
            }
        }
    return leftBorder;
}

**找右边界**



public int getRightBorder(int[] nums, int target){
    int left = 0;
    int right = nums.length - 1;
    int rightBorder = -2;
    while(left <= right){
        int mid = left + (right - left);
            if(nums[mid] > target){
                right = mid - 1;
            }else{
                //寻找右边界
                left = mid + 1;
                rightBorder = left;
            }
        }
    return rightBorder;    
}   

**分情况讨论了**



public int[] searchRange(int[] nums, int target) {
  int leftBorder = getLeftBorder(nums, target);
  int rightBorder = getRightBorder(nums, target);
  //数组中没有target,target在数组左边或右边
  if(leftBorder == -2 || rightBorder == -2){
      return new int[]{-1,-1};
  }
  //数组中有target,返回这两个target下标
  if(rightBorder -leftBorder >1){
      return new int[]{leftBorder + 1,rightBorder - 1};
  }
  //target在数组范围中,但数组不存在target
  return new int[]{-1,-1};
}



---



### 2.5 x的平方根


链接    [69. x 的平方根 - 力扣(LeetCode)](https://bbs.csdn.net/topics/618668825)


![](https://img-blog.csdnimg.cn/e8c82292c79a492ba35a0a1ae8ae173e.png)


 分析一下(因为本篇是只讲解二分查找的,别的方法不提,主要加强二分查找理解)


![](https://img-blog.csdnimg.cn/295b827c8fd740ab90060d78ee98c87d.png)



class Solution {
public int mySqrt(int x) {
int left = 0;
int right = x;
int ans = -1;
while(left <= right){
int mid = left + (right -left)/2;
if((long)mid*mid <= x){
//这里写乘法的,必须要转成long,不然会溢出
//或者直接写除法,就不考虑溢出了
ans = mid;
left = mid + 1;
}else{
right = mid -1;
}
}
return ans;
}
}




---



###  2.6 有效的完全平方数


链接  [367. 有效的完全平方数 - 力扣(LeetCode)](https://bbs.csdn.net/topics/618668825)


![](https://img-blog.csdnimg.cn/72c84b0f7f584dc6803f8db294d2a6cd.png)


 简单分析一下




![img](https://img-blog.csdnimg.cn/img_convert/6fd5d6df217e709785ff892bd15eb499.png)
![img](https://img-blog.csdnimg.cn/img_convert/b3d5c53ee4a30a708884ac4f11853eae.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

下




[外链图片转存中...(img-etuYklsa-1715558440780)]
[外链图片转存中...(img-g6P6Pe6b-1715558440780)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值