二分算法(模板)

例题1:

704. 二分查找 - 力扣(LeetCode)

算法原理:(二分)

通过遍历也可以通过,但是二分更优且数据量越大越能体现。

二分思路:

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:

162. 寻找峰值 - 力扣(LeetCode)

例题4:

153. 寻找旋转排序数组中的最小值 - 力扣(LeetCode)

相关推荐
李小白杂货铺2 分钟前
识别和破除信息茧房
算法·信息茧房·识别信息茧房·破除信息茧房·算法推荐型茧房·观点过滤型茧房·茧房
来荔枝一大筐41 分钟前
C++ LeetCode 力扣刷题 541. 反转字符串 II
c++·算法·leetcode
暴风鱼划水1 小时前
算法题(Python)数组篇 | 6.区间和
python·算法·数组·区间和
zl_vslam2 小时前
SLAM中的非线性优-3D图优化之轴角在Opencv-PNP中的应用(一)
前端·人工智能·算法·计算机视觉·slam se2 非线性优化
是苏浙2 小时前
零基础入门C语言之C语言实现数据结构之顺序表应用
c语言·数据结构·算法
lkbhua莱克瓦242 小时前
Java基础——常用算法3
java·数据结构·笔记·算法·github·排序算法·学习方法
小白程序员成长日记2 小时前
2025.11.07 力扣每日一题
数据结构·算法·leetcode
·白小白2 小时前
力扣(LeetCode) ——209. 长度最小的子数组(C++)
c++·算法·leetcode
小猪咪piggy2 小时前
【算法】day16 动态规划
算法·动态规划
ohnoooo92 小时前
251106 算法
数据结构·c++·算法