java二分查找算法详解

server/2024/12/19 7:06:03/

二分查找遵循分治策略,在升序排列的有序数组中查找元素。核心是反复减半搜索区间,先确定中间元素并与目标元素比较,若相等则查找成功返回其索引;若中间元素大于目标元素,就把搜索区间缩小到左半部分(更新右边界);若小于,则缩小到右半部分(更新左边界)。如此重复,直至找到目标元素或确定其不存在(左边界大于右边界时)。
 
例如数组 [1, 3, 5, 7, 9, 11, 13, 15],找7时中间元素就是7(索引3),能直接找到;找6时,因中间元素7大于6,就将搜索区间缩小至 [1, 3, 5] 继续重复操作,直至确定6不在数组中。

java 代码实现

java">public class Main {public static int binarySearch(int[] arr, int target) {int left = 0;int right = arr.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (arr[mid] == target) {return mid;} else if (arr[mid] < target) {left = mid + 1;} else {right = mid - 1;}}return -1;}public static void main(String[] args) {int[] arr = {1,2,3,4,5,6,7,8,9};int target = 9;int result = binarySearch(arr, target);if (result == -1) {System.out.println("目标元素未找到");} else {System.out.println("目标元素在索引 " + result + " 处");}}
}

在上述代码中, left 和 right 分别表示当前搜索区间的左右边界,通过循环不断调整这两个边界,直到找到目标元素或者 left 大于 right 。

*在计算中间索引 mid 时,使用 left + (right - left) / 2 而不是 (left + right) / 2 是为了防止在 left 和 right 很大时出现整数溢出的情况。

时间复杂度

二分查找的时间复杂度为O(log n),其中 n 是数组的长度,这是因为每次迭代都将搜索区间减半。在最坏的情况下,直到搜索区间缩小到只剩下一个元素才确定目标元素是否存在,需要进行log_2 n次比较。
 

二分查找的变体

在某些情况下,我们不仅要找到目标元素,还希望找到它在数组中第一次出现的位置。例如,在数组 [1, 2, 3, 4, 5, 6, 7, 8, 9, 9] 中查找 9,我们希望返回索引 8 而不是 9。

需要将代码改成:

java"> public static int binarySearch(int[] arr, int target) {int left = 0;int right = arr.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (arr[mid] == target) {if (mid == 0 || arr[mid - 1]!= target) {return mid;} else {right = mid - 1;}} else if (arr[mid] < target) {left = mid + 1;} else {right = mid - 1;}}return -1;}

当找到目标元素后,我们还需要检查它是否是第一个出现的,如果当前索引为 0 或者前一个元素不等于目标元素,那么就找到了第一个等于目标值的元素,否则继续在左半部分查找。

有时我们需要找到目标元素在数组中最后一次出现的位置,例如,在数组[1, 2, 3, 4, 5, 6, 7, 8, 9, 9] 中查找 9,我们希望返回索引 9。

java">public static int findLastEqual(int[] arr, int target) {int left = 0;int right = arr.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (arr[mid] == target) {if (mid == arr.length - 1 || arr[mid + 1]!= target) {return mid;} else {left = mid + 1;}} else if (arr[mid] < target) {left = mid + 1;} else {right = mid - 1;}}return -1;
}

同理,当找到目标元素后,检查它是否是最后一个出现的,如果当前索引为数组末尾或者后一个元素不等于目标元素,那么就找到了最后一个等于目标值的元素。

查找最后一个满足小于等于目标值条件的元素

java">public static int findLastLessEqual(int[] arr, int target) {int left = 0;int right = arr.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (arr[mid] <= target) {if (mid == arr.length - 1 || arr[mid + 1] > target) {return mid;} else {left = mid + 1;}} else {right = mid - 1;}}return -1;
}

当找到一个小于等于目标值的元素后,检查它是否是最后一个满足条件的,如果当前索引为数组末尾或者后一个元素大于目标值,那么就找到了最后一个小于等于目标值的元素,否则继续右分查找更大的满足条件的元素。

二分查找的常见错误及注意事项

  1. 在实现二分查找时,最常见的错误之一就是边界条件的处理不当。例如,在循环条件中使用 left < right 而不是 left <= right 可能会导致遗漏对最后一个元素的检查。
  2. 在计算中间索引 mid 时,如果简单地使用 (left + right) / 2 ,当 left 和 right 都很大时,可能会发生整数溢出。正确的做法是使用 left + (right - left) / 2 来避免这个问题。
  3.  二分查找的前提是数组必须是有序的,在使用二分查找之前要确保数组已经按照正确的顺序排序。

总结


通过深入理解二分查找原理、熟练掌握各种变体形式的实现以及注意在实际应用中的常见错误,程序员能够充分发挥其优势,提高程序的性能和效率。无论是在基础的编程任务还是复杂的算法设计和数据处理场景中,二分查找都将是一个不可或缺的有力工具,为解决各种实际问题提供高效可靠的解决方案。


http://www.ppmy.cn/server/151387.html

相关文章

scp命令

scp&#xff08;Secure Copy Protocol&#xff09;是一种用于在不同主机之间安全传输文件的命令。使用 scp 命令&#xff0c;你可以将文件从本地计算机复制到远程计算机&#xff0c;或者从远程计算机复制到本地计算机。 以下是 scp 命令的基本语法和一些示例&#xff1a; 基本…

压力测试Jmeter简介

前提条件&#xff1a;要安装JDK 若不需要了解&#xff0c;请直接定位到左侧目录的安装环节。 1.引言 在现代软件开发中&#xff0c;性能和稳定性是衡量系统质量的重要指标。为了确保应用程序在高负载情况下仍能正常运行&#xff0c;压力测试变得尤为重要。Apache JMeter 是一…

Django中注册模型到Admin界面

Django 是一个高级的 Python Web 框架,它鼓励快速开发和干净、务实的设计。Django 自带了一个强大的管理后台(Admin),可以让开发者轻松地管理数据库中的数据。在这篇博文中,我们将详细介绍如何在 Django Admin 中注册一个模型,并定制其显示和管理方式。 前提条件 在开始…

Windows server 服务器网络安全管理之防火墙出站规则设置

Windows server 服务器网络安全管理之防火墙出站规则设置 创建一条出站规则 这条出站规则针对IE浏览器设置&#xff0c;指定路径 TCP协议和指定端口&#xff08;多个端口的写法要注意&#xff09; 所有IP&#xff0c;所有应用&#xff0c;都采用阻止 给这条规则进行命名…

sql-labs(16-20)

第十六关 这一关与15关的注入方式一样&#xff0c;都是使用盲注可以实现&#xff0c;只是闭合方式不同&#xff0c;这里需要使用")来闭合&#xff0c;就里就不再演示 第一步进行时间盲注 ") and sleep(3)# 第二步开始判断数据库的长度 第三步爆出表名 第四步爆出字…

音视频入门基础:MPEG2-TS专题(18)——PES流简介

一、PES流 《T-REC-H.222.0-202106-S!!PDF-E.pdf》第32页对PES进行了定义。音视频及数字信号经过MPEG-2编码器进行数据压缩&#xff0c;形成基本码流&#xff08;ES流&#xff09;&#xff0c;ES流再打包形成带有包头的码流&#xff0c;就是PES&#xff08;Packetized Element…

Redis在库存里的应用

(1)社区电商系统库存模块的设计要求 由于该库存模块可以支持高性能的并发读写,因此需要支持对商品库存进行多分片写入和读取处理(分片一般等于节点),需要提供单个分片库存不足以扣减时的合并库存功能,以及需要提供操作商品入库时的库存渐进性写入缓存的实现。 也就是对于热…

Scratch教学作品 | 圣诞节平台游戏——在节日中挑战冒险,收集礼物吧! ✨

今天给大家推荐一款节日氛围拉满的Scratch平台游戏——《圣诞滚动平台游戏》&#xff01;这款作品将冒险、挑战与圣诞元素完美结合&#xff0c;让你在收集礼物的过程中锻炼反应力与操作技巧&#xff0c;同时沉浸在温暖的节日氛围中&#xff01;&#x1f384; 更棒的是&#xff…