【数据结构】二分查找5.12

Basic

需求:在有序数组A内,查找值target

如果找到返回索引

如果找不到返回-1


算法描述

前提:给定一个内含n个元素的有序数组A(升序),一个待查找值

设置两个索引:i=0;j=n-1;

如果j>i,查找停止

设置m=floor(i+j/2),floor为向下取整的最小整数

如果target>m,设置i=m+1;

如果traget<m,设置j=m-1;

如果traget=m,找到待查找值。

实现

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 -1;
	}

}

问题1:

为什么是i<=j,而不是i<j?

i,j区间内会有未比较的元素,i<=j它们共同指向的元素也可以遍历到。

问题2:

(i+j)/2有没有问题?

若数字较大,再次循环:

i=m+1;

m=(i+j)/2;会超出范围变成负数

同一个二进制数,第一位是否是符号位。会使数值展现不同。(Java中会考虑符号位)

可以通过无符号右移来达到除2效果。

解决方法:

无符号右移>>>

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 -1;
	}

}

额外应用:

(0+7)/2 3.5 //不需要设置float,可当成整数

(0+7)>>>1 3

练习优化过程

Pocess1超出时间限制

class Solution {

public int searchInsert(int[] nums, int target) {

int i=0,j=nums.length-1;

int m=(i+j)>>>1;

int index=0;

while(i<=j){

index++;

if(target<m){

j=m-1;

}else if(m<target){

i=m+1;

}else{

return index;

}

}

for(int k=0;k<nums.length;k++){

while(target>nums[k]){

index=k+1;

}

}

return index;

}

}

问题分析:

  1. 二分查找逻辑错误:比较 target 和 m(中间索引)而不是 nums[m](中间值)。

  2. 无限循环:在二分查找部分,没有更新 m的值,导致循环条件永远不变。

  3. 错误的索引计算:在二分查找中返回的是 index(循环次数)而不是正确的位置。

  4. 不必要的线性搜索:最后的线性搜索部分既不正确也不必要。i就是应该插入的位置。

Process2优化

class Solution {

public int searchInsert(int[] nums, int target) {

int i = 0, j = nums.length - 1;

while (i <= j) {

int m = (i + j) >>> 1;

if (nums[m] == target) {

return m;

} else if (nums[m] < target) {

i = m + 1;

} else {

j = m - 1;

}

return i;

}

}

相关推荐
BillKu1 分钟前
Java中List的forEach用法详解
java·windows·list
重生之后端学习3 分钟前
苍穹外卖-day03
java·开发语言·数据库·spring boot·mysql·spring·tomcat
Splendid10 分钟前
Geneformer:基于Transformer的基因表达预测深度学习模型
javascript·算法
程序员阿超的博客11 分钟前
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
java·spring boot·安全·spring
愿所愿皆可成24 分钟前
机器学习之聚类Kmeans算法
算法·机器学习·kmeans·聚类
幻奏岚音25 分钟前
统计学(第8版)——假设检验学习笔记(考试用)
笔记·学习·算法
异常君31 分钟前
Java 应用中构建 Elasticsearch 多层次缓存:提升查询效率的实战方案
java·elasticsearch·架构
hie9889443 分钟前
基于matlab策略迭代和值迭代法的动态规划
算法·动态规划
Coovally AI模型快速验证1 小时前
SFTrack:面向警务无人机的自适应多目标跟踪算法——突破小尺度高速运动目标的追踪瓶颈
人工智能·神经网络·算法·yolo·计算机视觉·目标跟踪·无人机
橘子编程1 小时前
Maven从入门到精通指南
java·maven