网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事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行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**