二分法题目:在有序数组中A内,查找数组中的某一个元素的下标(本题是从由小到大的顺序)

本文主要是介绍二分法题目:在有序数组中A内,查找数组中的某一个元素的下标(本题是从由小到大的顺序),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

二分查找算法,也称为折半查找算法,是一种在有序数组中查找特定元素的高效算法。它的基本思想是将查找的区间逐渐缩小,直到找到目标元素或者确定目标元素不存在。

算法步骤如下:

  1. 初始化:首先,确定数组的左右边界,通常初始时左边界为数组的起始索引,右边界为数组的末尾索引。

  2. 找到中间元素:计算左右边界的中间索引,然后取得该索引处的元素值。

  3. 比较中间元素

    • 如果中间元素等于目标值,查找成功,返回元素索引。
    • 如果中间元素大于目标值,说明目标值应该在左半边,将右边界移动到中间索引的左边一位。
    • 如果中间元素小于目标值,说明目标值应该在右半边,将左边界移动到中间索引的右边一位。
  4. 重复:在新的查找区间中,重复步骤2和步骤3,直到左边界大于右边界,此时查找失败,返回-1,或者返回指示元素不存在的其他值。

算法特点

  • 二分查找算法的时间复杂度是O(log n),其中n是数组的大小。这是因为每一次比较都将查找范围缩小为原来的一半。

  • 但是,二分查找算法要求输入的数据必须是有序的。如果数组无序,需要事先进行排序操作。

  • 由于二分查找每次将查找范围缩小为一半,因此它的效率非常高,尤其是在大型数据集中的查找操作。

  • 二分查找算法是一种迭代的算法,也可以使用递归实现。

Java版:

package LeetCode_1.Binary_search;
//小淼的算法之路//二分法题目:在有序数组中A内,查找数组中的某一个元素的下标(本题是从由小到大的顺序)public class Binary_search {//二分查找算法版本1.0public static int BinarySearchBasic(int[] a, int target){int i = 0,j = a.length -1;//设置指针和初值while (i <= j){int m = (i + j)>>>1;//m:中间值if(target < a[m]){//若查找的在中间值左边(小于中间值),最大值指针j占据中间值-1的位置,在进行计算j = m -1;} else if (a[m] < target){//若查找的在中间值右边(大于中间值),最小值指针j占据中间值+1的位置,在进行计算i = m + 1;} else {return m;//否则就是target值与中间值相等,直接返回中间值}}return -1;//不存在时返回-1,因为能找到的都在数组当中,在数组中的都有一个索引值,所以能找到的输出的数组索引值不可能为-1}/*本题问题1:为什么i<=j 意味着区间未比较的元素,而不是i<j  ?*       答:因为i,j 它们指向的元素也会参与比较,若i<j,则参与比较的只能是i与j中间的值,若这时i与j指向的元素相同则该算法会发生错误。* 本题问题2:为什么int m = (i + j)>>>1;,而不是int m = (i + j) / 2;  ?*       答:如果使用int m = (i + j) / 2 来确定中间值的话多次循环会有问题:这与二进制的第一位是不是符号位有关(1:负,0:正)。*           然而int m = (i + j)>>>1 这种方式:将i+j表示成的二进制整体向右移动一位(二进制对应的十进制做/2操作)* *///二分查找算法版本2.0public static int BinarySearchUpgrades(int[] a, int target){int i = 0,j = a.length;         //第一处改动while (i < j){                  //第二处改动int m = (i + j)>>>1;if(target < a[m]){j = m;                  //第三处改动} else if (a[m] < target){i = m + 1;} else {return m;}}return -1;}//测试类public static void main(String[] args) {int[] a = {7,13,21,30,38,44,52,53,78,79,88,89,91,92,93,94};int target = 92;long startTime = System.nanoTime();;//开始时时间点int result = BinarySearchBasic(a, target);//执行的算法long endTime = System.nanoTime();//结束时时间点long elapsedTime = endTime - startTime;//算法占用时间if (result != -1) {System.out.println("二分查找法1.0版本----------"+"目标值 " + target + " 在数组中的索引是 " + result+"\n"+"算法执行时间(纳秒): " + elapsedTime);} else {System.out.println("二分查找法1.0版本----------"+"目标值 " + target + " 未在数组中找到");}long startTime_1 = System.nanoTime();;//开始时时间点int result_1 = BinarySearchUpgrades(a, target);long endTime_1 = System.nanoTime();//结束时时间点long elapsedTime_1 = endTime_1 - startTime_1;//算法占用时间if (result_1 != -1) {System.out.println("二分查找法2.0版本----------"+"目标值 " + target + " 在数组中的索引是 " + result_1+"\n"+"算法执行时间(纳秒): " + elapsedTime_1);} else {System.out.println("二分查找法2.0版本----------"+"目标值 " + target + " 未在数组中找到");}}
}

JavaScript:

function binarySearchBasic(a, target) {let i = 0, j = a.length - 1; // 设置指针和初值while (i <= j) {let m = (i + j) >>> 1; // m:中间值if (target < a[m]) {// 若查找的在中间值左边(小于中间值),最大值指针j占据中间值-1的位置,在进行计算j = m - 1;} else if (a[m] < target) {// 若查找的在中间值右边(大于中间值),最小值指针j占据中间值+1的位置,在进行计算i = m + 1;} else {return m; // 否则就是target值与中间值相等,直接返回中间值}}return -1; // 不存在时返回-1,因为能找到的都在数组当中,在数组中的都有一个索引值,所以能找到的输出的数组索引值不可能为-1
}function binarySearchUpgrades(a, target) {let i = 0, j = a.length; // 第一处改动while (i < j) { // 第二处改动let m = (i + j) >>> 1;if (target < a[m]) {j = m; // 第三处改动} else if (a[m] < target) {i = m + 1;} else {return m;}}return -1;
}const a = [7, 13, 21, 30, 38, 44, 52, 53, 78, 79, 88, 89, 91, 92, 93, 94];
const target = 92;let startTime = performance.now(); // 开始时时间点
let result = binarySearchBasic(a, target);
let endTime = performance.now(); // 结束时时间点
let elapsedTime = endTime - startTime; // 算法占用时间if (result !== -1) {console.log(`二分查找法1.0版本---------- 目标值 ${target} 在数组中的索引是 ${result}\n算法执行时间(毫秒): ${elapsedTime}`);
} else {console.log(`二分查找法1.0版本---------- 目标值 ${target} 未在数组中找到`);
}let startTime1 = performance.now(); // 开始时时间点
let result1 = binarySearchUpgrades(a, target);
let endTime1 = performance.now(); // 结束时时间点
let elapsedTime1 = endTime1 - startTime1; // 算法占用时间if (result1 !== -1) {console.log(`二分查找法2.0版本---------- 目标值 ${target} 在数组中的索引是 ${result1}\n算法执行时间(毫秒): ${elapsedTime1}`);
} else {console.log(`二分查找法2.0版本---------- 目标值 ${target} 未在数组中找到`);
}

这篇关于二分法题目:在有序数组中A内,查找数组中的某一个元素的下标(本题是从由小到大的顺序)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/280510

相关文章

JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法

《JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法》:本文主要介绍JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法,每种方法结合实例代码给大家介绍的非常... 目录引言:为什么"相等"判断如此重要?方法1:使用some()+includes()(适合小数组)方法2

python 线程池顺序执行的方法实现

《python线程池顺序执行的方法实现》在Python中,线程池默认是并发执行任务的,但若需要实现任务的顺序执行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录方案一:强制单线程(伪顺序执行)方案二:按提交顺序获取结果方案三:任务间依赖控制方案四:队列顺序消

C#高效实现Word文档内容查找与替换的6种方法

《C#高效实现Word文档内容查找与替换的6种方法》在日常文档处理工作中,尤其是面对大型Word文档时,手动查找、替换文本往往既耗时又容易出错,本文整理了C#查找与替换Word内容的6种方法,大家可以... 目录环境准备方法一:查找文本并替换为新文本方法二:使用正则表达式查找并替换文本方法三:将文本替换为图

Python中高级文本模式匹配与查找技术指南

《Python中高级文本模式匹配与查找技术指南》文本处理是编程世界的永恒主题,而模式匹配则是文本处理的基石,本文将深度剖析PythonCookbook中的核心匹配技术,并结合实际工程案例展示其应用,希... 目录引言一、基础工具:字符串方法与序列匹配二、正则表达式:模式匹配的瑞士军刀2.1 re模块核心AP

Java中数组与栈和堆之间的关系说明

《Java中数组与栈和堆之间的关系说明》文章讲解了Java数组的初始化方式、内存存储机制、引用传递特性及遍历、排序、拷贝技巧,强调引用数据类型方法调用时形参可能修改实参,但需注意引用指向单一对象的特性... 目录Java中数组与栈和堆的关系遍历数组接下来是一些编程小技巧总结Java中数组与栈和堆的关系关于

把Python列表中的元素移动到开头的三种方法

《把Python列表中的元素移动到开头的三种方法》在Python编程中,我们经常需要对列表(list)进行操作,有时,我们希望将列表中的某个元素移动到最前面,使其成为第一项,本文给大家介绍了把Pyth... 目录一、查找删除插入法1. 找到元素的索引2. 移除元素3. 插入到列表开头二、使用列表切片(Lis

Spring Bean初始化及@PostConstruc执行顺序示例详解

《SpringBean初始化及@PostConstruc执行顺序示例详解》本文给大家介绍SpringBean初始化及@PostConstruc执行顺序,本文通过实例代码给大家介绍的非常详细,对大家的... 目录1. Bean初始化执行顺序2. 成员变量初始化顺序2.1 普通Java类(非Spring环境)(

浅析Spring如何控制Bean的加载顺序

《浅析Spring如何控制Bean的加载顺序》在大多数情况下,我们不需要手动控制Bean的加载顺序,因为Spring的IoC容器足够智能,但在某些特殊场景下,这种隐式的依赖关系可能不存在,下面我们就来... 目录核心原则:依赖驱动加载手动控制 Bean 加载顺序的方法方法 1:使用@DependsOn(最直

Java中的数组与集合基本用法详解

《Java中的数组与集合基本用法详解》本文介绍了Java数组和集合框架的基础知识,数组部分涵盖了一维、二维及多维数组的声明、初始化、访问与遍历方法,以及Arrays类的常用操作,对Java数组与集合相... 目录一、Java数组基础1.1 数组结构概述1.2 一维数组1.2.1 声明与初始化1.2.2 访问

MySQL中查找重复值的实现

《MySQL中查找重复值的实现》查找重复值是一项常见需求,比如在数据清理、数据分析、数据质量检查等场景下,我们常常需要找出表中某列或多列的重复值,具有一定的参考价值,感兴趣的可以了解一下... 目录技术背景实现步骤方法一:使用GROUP BY和HAVING子句方法二:仅返回重复值方法三:返回完整记录方法四: