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

【数据结构】二分查找(返回插入点)5.14

二分查找基础版

package 二分查找;
public class BinarySearch { 	
public static void main(String[] args) {		// TODO Auto-generated method stub	}     public static int
binarySearchBasic(int[] a,int target) {    	 int i=0,j=a.length-1; //设置指针初值    	 
while(i<=j) { //范围有内容    		 
int m=(i+j)/2;    		 
if(target<a[m]) {    			 
j=m-1;    		 
}else if(target>a[m]) {    			 i=m+1;    		 
}else {    			 
return m;    		 
}    	 
}    	 
return -1;	} 
}

说明:
若目标在最左边,判断语句执行L次
若目标在最右边,判断语句执行2*L次
不平衡

平衡版
目的:为了减少执行次数

package 二分查找;
public class BinarySearch { 	
public static void main(String[] args) {		// TODO Auto-generated method stub	}     public static int
binarySearchBasic(int[] a,int target) {    	 int i=0,j=a.length; //设置指针初值    	 
while(1<j-i) { //范围有内容  		 
int m=(i+j)>>>2;    		 
if(target<a[m]) {    			 
j=m;    		 //边界改变  		 
}else {    			 
i=m;    		 //若i=m+1,当目标等于中间值时会错过}    	 
}  
if(a[m]==traget)return i;elsereturn -1;} 
}

Java版

package 二分查找;
public class BinarySearch { 	
public static void main(String[] args) {		// TODO Auto-generated method stub	}     public static int
binarySearchBasic(int[] a,int target) {    	 int i=0,j=a.length-1; //设置指针初值    	 
while(i<=j) { //范围有内容    		 
int m=(i+j)/2;    		 
if(target<a[m]) {    			 
j=m-1;    		 
}else if(target>a[m]) {    			 i=m+1;    		 
}else {    			 
return m;    		 
}    	 
}    	 
return -(i+1;	//返回值 -插入点-1
} 
}

源码

private static int binarySearch0(int[] a, int key) {int low = 0, high = a.length - 1;    while (low <= high) {        
int mid = (low + high) >>> 1;        
if (a[mid] < key) 
low = mid + 1;        
else if (a[mid] > key) 
high = mid - 1;        
else return mid; // 找到时返回下标    
}    
return -(low + 1); // 未找到时返回插入点编码
}

为什么这样设计?
// 编码过程
返回值 = -(插入点 + 1)
// 解码过程插入点 = -返回值 - 1

  1. 保留插入点信息
    通过数学变换,你可以反向计算出插入位置:
    插入点 = -(返回值 + 1)
    例如 -2 → -( -2 + 1 ) = 1

  2. 避免歧义
    如果直接返回 -插入点,当插入点是 0 时,返回值也是 0,这会和「找到目标且下标为0」的情况冲突。

  3. 效率优化
    查找时已经计算出了插入点,直接返回可以避免二次查找。

插入元素

int[] a = {2, 5, 8};  // 已经排好序的数组
int target = 4;        // 我们要查找/插入的数字
int i = Arrays.binarySearch(a, target);
//Java中的二分查找
int insertIndex = Math.abs(i + 1);//实际插入位置
int[] b = new int[a.length + 1];  // 新数组长度比原数组大1
// 1. 复制插入点前的元素(不包含插入点)
System.arraycopy(a, 0, b, 0, insertIndex);
// 参数解释:
// a: 源数组
// 0: 从源数组的哪个位置开始复制
// b: 目标数组
// 0: 放到目标数组的哪个位置
// insertIndex: 要复制多少个元素// 2. 插入新元素
b[insertIndex] = target;// 3. 复制插入点后的元素
System.arraycopy(a, insertIndex, b, insertIndex + 1, a.length - insertIndex);
// 参数解释:
// a: 源数组
// insertIndex: 从源数组的哪个位置开始复制
// b: 目标数组
// insertIndex + 1: 放到目标数组的哪个位置(跳过插入的新元素)
// a.length - insertIndex: 要复制多少个元素

为什么这样设计?
这种设计的好处:
1)保持数组始终有序
2)插入操作高效(使用 System.arraycopy 是本地方法,速度很快)
3)利用了二分查找的高效性(O(log n))

http://www.lryc.cn/news/2380215.html

相关文章:

  • 如何设计一个二级缓存(Redis+Caffeine)架构?Redis 6.0多线程模型如何工作?
  • Java:logback-classic与slf4j版本对应关系
  • 【OpenGL学习】(一)创建窗口
  • AI大语言模型评测体系演进与未来展望
  • 微服务项目->在线oj系统(Java版 - 5)
  • disryptor和rabbitmq
  • HTTP与HTTPS协议的核心区别
  • Flink 并行度的设置
  • 【微服务】SpringBoot + Docker 实现微服务容器多节点负载均衡详解
  • get请求使用数组进行传参
  • 20. 自动化测试框架开发之Excel配置文件的IO开发
  • 【MySQL成神之路】MySQL常用语法总结
  • Linux动静态库制作与原理
  • 确保高质量的音视频通话,如何最大化利用视频带宽
  • ffmpeg 把一个视频复制3次
  • GPT/Claude3国内免费镜像站更新 亲测可用
  • AI自动化工作流:开启当下智能生产力的价值
  • stm32——EXTI外部中断
  • Python:操作Excel按行写入
  • Redis进阶知识
  • Python机器学习笔记(二十三 模型评估与改进-网格搜索)
  • 12.vue整合springboot首页显示数据库表-实现按钮:【添加修改删除查询】
  • bisheng系列(一)- 本地部署(Docker)
  • 如何用Python批量解压ZIP文件?快速解决方案
  • DriveGenVLM:基于视觉-语言模型的自动驾驶真实世界视频生成
  • JavaScript 中的五种继承方式进行深入对比
  • 企业标准信息公共服务平台已开放标准通编辑器访问入口
  • [Linux]安装吧!我的软件包管理器!
  • Spring Boot 与 RabbitMQ 的深度集成实践(三)
  • 进阶-数据结构部分:1、数据结构入门