例题1:
算法原理:(二分)
通过遍历也可以通过,但是二分更优且数据量越大越能体现。
二分思路:
1.mid1 = (left + right)/2 与 mid2 = right + (right - left)/2区别。
如果不考虑数据范围: (left + right)/2 = right + (right - left)/2,但越界就不一样了。
mid1 = (left + right)/2 :可能越界
mid2 = left+ (right - left)/2 : 可以防止越界
2.mid1 = (right + left)/2 与 mid2 = (right + left + 1)/2区别。
(right + left)/2 : 向下取整
(right + left + 1)/2 :向上取整
举个例子: right = 3,left = 4,(right + left)/2 = 3,(right + left + 1)/2 = 4;
right = 2,left = 4,(right + left)/2 = 3,(right + left + 1)/2 = 3;
这里不会严格用数学方式去证明,那样太花时间了,感兴趣的话网上搜搜,我们直接给出结论,当right + left 结果为偶数时,mid1 与 mid2 是没有区别的,但结果为奇数时就会相差1,不要小看了这一点区别,不注意这里,就很有可能写出死循环,具体我们在下面例题里体现。

这里不能通过调整上下取整的方式来避免死循环。但是可以通过增加一行代码来弄
( if(left == right && nums[left] != target) break; )
代码:
java
//暴力可以过😯
public int search(int[] nums, int target) {
int n = nums.length;
for(int i = 0;i < n;i++){
if(nums[i] > target){
break;
}
if(nums[i] == target) return i;
}
return -1;
}
java
//二分
public int search(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){
left = mid+1;
}else if(nums[mid] ==target){
return mid;
}else {
right = mid-1;
}
}
return -1;
}
java
//二分,调整后
public int search(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){
left = mid+1;
}else if(nums[mid] ==target){
return mid;
}else {
right = mid;
}
if(left == right && nums[left] != target) break;
}
return -1;
}


通过上面两幅幅图我们就可以感受到上,下取整差1,如果调整不好便会出现死循环。这里只列举了向下取整,避免死循环情况。还有一种是向上取整,避免死循环情况。(再往下的例题就不会,所这么多了。)
如下例题都是可以利用二分解决的,这里就提一点,二分的使用场景并不一定非要整个序列有序,而是依据你的需求,巧妙的去使用它。
例题2:
34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)
例题3:
例题4: