【二分算法】模板总结

目录

一、二分查找时间复杂度

二、二分查找模板

[2.1 模板一:标准的二分查找](#2.1 模板一:标准的二分查找)

[2.2 模板二:二分查找左边界](#2.2 模板二:二分查找左边界)

[2.3 模板三:二分查找右边界](#2.3 模板三:二分查找右边界)

三、总结:


一、二分查找时间复杂度

时间复杂度可以表示 O(n)=O(log2​n)或者O(n)=O(logn)

二、二分查找模板

什么时候可能需要用二分查找?

(1)待查找的数组有序或者部分有序

(2)可以发现二段性

(3)题目要求时间复杂度低于 O(n),或者直接要求时间复杂度为 O(log n)

2.1 模板一:标准的二分查找

适用场景:数组元素有序且不重复

java 复制代码
public int search(int[] nums, int target) {
        int left = 0,right = nums.length-1;
        while(left<=right) {
            int mid = left + ((right-left)>>1);//+运算的优先级高
            if(target==nums[mid]) return mid;
            else if(nums[mid]<target) left = mid+1;
            else right = mid-1;
        }
        return -1;
    }

注意点:

(1)为什么 while 循环的条件是 <=,而不是 < ?

当元素只有一个且这个元素正好就是目标值,那么没有=就进入不了循环,得不到正确的结果

(2)计算 mid 时需要防止溢出

left + ((right -left) >> 1) 其实和 (left + right) / 2 是等价的,这样写的目的一个是为了防止 (left + right) 出现溢出,另外用位运算替代除法提升性能


2.2 模板二:二分查找左边界

java 复制代码
public int search(int[] nums, int target) {
        int left =0,right = nums.length-1;
        while(left<right) {//1.
            int mid = left+(right-left)/2;//2.
            if(nums[mid]<target) left = mid+1;//3.
            else right = mid;
        }
        if(nums[left]==target) return left;
        return -1;
    }

注意点:

(1)为什么 while 循环的条件是 <,而不是 <= ?

left等于right的时候就已经得到了最终结果,如果判断了,就会进入死循环,因为right后面一直不动

(2) 求中点的操作

求左边界根标准模板一样,不用+1,直接left+(right-left)/2(总个数为偶数个时取中点的时候取左边那个

(3)为啥nums[mid]==target右边界也要变

要寻找左边界,当nums[mid] == target,这个mid的位置不一定就是最左侧的那个边界,所以还要继续收缩右边界

2.3 模板三:二分查找右边界

java 复制代码
public int search(int[] nums, int target) {
        int left =0,right = nums.length-1;
        while(left<right) {//1.
            int mid = left+(right-left+1)/2;//2.
            if(nums[mid]>target) right = mid-1;//3.
            else left=mid;
        }
        if(nums[right]==target) return right;
        return -1;
    }

注意点:

(1)为什么 while 循环的条件是 <,而不是 <= ?

left等于right的时候就已经得到了最终结果,如果判断了,就会进入死循环,因为right后面一直不动

(2) 求中点的操作

这个和求左边界不一样,需要+1,即left+(right-left+1)/2(总个数为偶数个时取中点的时候取右边那个),因为如果最后剩两个元素的时候,left一直找左边那个元素,那么将会进入死循环

(3)为啥nums[mid]==target左边界也要变

要寻找右边界,当nums[mid] == target,这个mid的位置不一定就是最右侧的那个边界,所以还要继续收缩左边界


三、总结:

(1)左+1,右不变

找左边界时,left = mid+1;找右边界,left = mid

(2)下面出现-1的时候,上面就要+1

mid-1出现,那么上面求mid就需要+1

相关推荐
sweetheart7-714 分钟前
LeetCode20. 有效的括号(2024冬季每日一题 11)
c++·算法·力扣··括号匹配
Mr.谢尔比25 分钟前
李宏毅机器学习课程知识点摘要(1-5集)
人工智能·pytorch·深度学习·神经网络·算法·机器学习·计算机视觉
我是博博啦27 分钟前
matlab例题
人工智能·算法·matlab
ö Constancy1 小时前
设计LRU缓存
c++·算法·缓存
香菜大丸1 小时前
leetcode 面试150之 156.LUR 缓存
算法
infiniteWei1 小时前
【Lucene】搜索引擎和文档相关性评分 BM25 算法的工作原理
算法·搜索引擎·lucene
2402_871321952 小时前
MATLAB方程组
gpt·学习·线性代数·算法·matlab
Mongxin_Chan2 小时前
【Cpp】指针与引用
c++·算法
非自律懒癌患者2 小时前
Transformer中的Self-Attention机制如何自然地适应于目标检测任务
人工智能·算法·目标检测
SSL_lwz2 小时前
P11290 【MX-S6-T2】「KDOI-11」飞船
c++·学习·算法·动态规划