当前位置: 首页 > article >正文

【二分算法】模板总结

目录

一、二分查找时间复杂度

二、二分查找模板

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

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

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

三、总结:


一、二分查找时间复杂度

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

二、二分查找模板

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

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

(2)可以发现二段性

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

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

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

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 模板二:二分查找左边界

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 模板三:二分查找右边界

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


http://www.kler.cn/news/317025.html

相关文章:

  • QT菜单之快捷菜单设计
  • 解决方案:spark数据进行加工转换后,进行数据存储的时候,发现数据行为空
  • STM32如何修改外部晶振频率和主频
  • 用递归函数实现汉诺塔游戏
  • 使用命令行 (Anaconda Prompt)
  • Spring Boot | 使用 `@Scheduled`: 定时任务的实现与优化
  • MySQL和SQL的区别简单了解和分析使用以及个人总结
  • 面向对象 vs 面向过程
  • Unreal Engine 5 C++: 插件编写03 | MessageDialog
  • 线上搭子小程序:随时随地找搭子!
  • 详解Linux中cat命令
  • 软件开发详解:通过源码搭建高效的食堂采购与供应链管理平台
  • VOC2007数据集
  • Linux高级I/O:多路转接模型
  • 计算机毕业设计 校园志愿者管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解
  • Linux进程间通信——Socket套接字
  • 计算机毕业设计 | SSM 凌云招聘平台 求职问答审批系统(附源码)
  • 【智能制造-32】通信冗余
  • win10 win11 设置文件权限以解决Onedrive不能同步问题
  • [Linux]:信号(下)
  • 计算机毕业设计 玩具租赁系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试
  • Can‘t get Kerberos realm
  • 智能体趋势:未来科技的核心驱动力
  • 4款AI生成PPT工具推荐,提升工作效率
  • 6个Python小游戏项目源码【免费】
  • 前端常见面试-首页性能提升、项目优化
  • leetcode第二十六题:删去有序数组的重复项
  • JavaScript 中的日期与时间处理
  • 設置Android設備全局代理
  • Fastapi做成docker启动失败,需要启动线程。