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


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

    算法步骤如下:

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

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

    3. 比较中间元素

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

    算法特点

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

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

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

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

    Java版:

    1. package LeetCode_1.Binary_search;
    2. //小淼的算法之路
    3. //二分法题目:在有序数组中A内,查找数组中的某一个元素的下标(本题是从由小到大的顺序)
    4. public class Binary_search {
    5. //二分查找算法版本1.0
    6. public static int BinarySearchBasic(int[] a, int target){
    7. int i = 0,j = a.length -1;//设置指针和初值
    8. while (i <= j){
    9. int m = (i + j)>>>1;//m:中间值
    10. if(target < a[m]){//若查找的在中间值左边(小于中间值),最大值指针j占据中间值-1的位置,在进行计算
    11. j = m -1;
    12. } else if (a[m] < target){//若查找的在中间值右边(大于中间值),最小值指针j占据中间值+1的位置,在进行计算
    13. i = m + 1;
    14. } else {
    15. return m;//否则就是target值与中间值相等,直接返回中间值
    16. }
    17. }
    18. return -1;//不存在时返回-1,因为能找到的都在数组当中,在数组中的都有一个索引值,所以能找到的输出的数组索引值不可能为-1
    19. }
    20. /*本题问题1:为什么i<=j 意味着区间未比较的元素,而不是i
    21. * 答:因为i,j 它们指向的元素也会参与比较,若i
    22. * 本题问题2:为什么int m = (i + j)>>>1;,而不是int m = (i + j) / 2; ?
    23. * 答:如果使用int m = (i + j) / 2 来确定中间值的话多次循环会有问题:这与二进制的第一位是不是符号位有关(1:负,0:正)。
    24. * 然而int m = (i + j)>>>1 这种方式:将i+j表示成的二进制整体向右移动一位(二进制对应的十进制做/2操作)
    25. * */
    26. //二分查找算法版本2.0
    27. public static int BinarySearchUpgrades(int[] a, int target){
    28. int i = 0,j = a.length; //第一处改动
    29. while (i < j){ //第二处改动
    30. int m = (i + j)>>>1;
    31. if(target < a[m]){
    32. j = m; //第三处改动
    33. } else if (a[m] < target){
    34. i = m + 1;
    35. } else {
    36. return m;
    37. }
    38. }
    39. return -1;
    40. }
    41. //测试类
    42. public static void main(String[] args) {
    43. int[] a = {7,13,21,30,38,44,52,53,78,79,88,89,91,92,93,94};
    44. int target = 92;
    45. long startTime = System.nanoTime();;//开始时时间点
    46. int result = BinarySearchBasic(a, target);//执行的算法
    47. long endTime = System.nanoTime();//结束时时间点
    48. long elapsedTime = endTime - startTime;//算法占用时间
    49. if (result != -1) {
    50. System.out.println("二分查找法1.0版本----------"+"目标值 " + target + " 在数组中的索引是 " + result+"\n"+"算法执行时间(纳秒): " + elapsedTime);
    51. } else {
    52. System.out.println("二分查找法1.0版本----------"+"目标值 " + target + " 未在数组中找到");
    53. }
    54. long startTime_1 = System.nanoTime();;//开始时时间点
    55. int result_1 = BinarySearchUpgrades(a, target);
    56. long endTime_1 = System.nanoTime();//结束时时间点
    57. long elapsedTime_1 = endTime_1 - startTime_1;//算法占用时间
    58. if (result_1 != -1) {
    59. System.out.println("二分查找法2.0版本----------"+"目标值 " + target + " 在数组中的索引是 " + result_1+"\n"+"算法执行时间(纳秒): " + elapsedTime_1);
    60. } else {
    61. System.out.println("二分查找法2.0版本----------"+"目标值 " + target + " 未在数组中找到");
    62. }
    63. }
    64. }

    JavaScript:

    1. function binarySearchBasic(a, target) {
    2. let i = 0, j = a.length - 1; // 设置指针和初值
    3. while (i <= j) {
    4. let m = (i + j) >>> 1; // m:中间值
    5. if (target < a[m]) {
    6. // 若查找的在中间值左边(小于中间值),最大值指针j占据中间值-1的位置,在进行计算
    7. j = m - 1;
    8. } else if (a[m] < target) {
    9. // 若查找的在中间值右边(大于中间值),最小值指针j占据中间值+1的位置,在进行计算
    10. i = m + 1;
    11. } else {
    12. return m; // 否则就是target值与中间值相等,直接返回中间值
    13. }
    14. }
    15. return -1; // 不存在时返回-1,因为能找到的都在数组当中,在数组中的都有一个索引值,所以能找到的输出的数组索引值不可能为-1
    16. }
    17. function binarySearchUpgrades(a, target) {
    18. let i = 0, j = a.length; // 第一处改动
    19. while (i < j) { // 第二处改动
    20. let m = (i + j) >>> 1;
    21. if (target < a[m]) {
    22. j = m; // 第三处改动
    23. } else if (a[m] < target) {
    24. i = m + 1;
    25. } else {
    26. return m;
    27. }
    28. }
    29. return -1;
    30. }
    31. const a = [7, 13, 21, 30, 38, 44, 52, 53, 78, 79, 88, 89, 91, 92, 93, 94];
    32. const target = 92;
    33. let startTime = performance.now(); // 开始时时间点
    34. let result = binarySearchBasic(a, target);
    35. let endTime = performance.now(); // 结束时时间点
    36. let elapsedTime = endTime - startTime; // 算法占用时间
    37. if (result !== -1) {
    38. console.log(`二分查找法1.0版本---------- 目标值 ${target} 在数组中的索引是 ${result}\n算法执行时间(毫秒): ${elapsedTime}`);
    39. } else {
    40. console.log(`二分查找法1.0版本---------- 目标值 ${target} 未在数组中找到`);
    41. }
    42. let startTime1 = performance.now(); // 开始时时间点
    43. let result1 = binarySearchUpgrades(a, target);
    44. let endTime1 = performance.now(); // 结束时时间点
    45. let elapsedTime1 = endTime1 - startTime1; // 算法占用时间
    46. if (result1 !== -1) {
    47. console.log(`二分查找法2.0版本---------- 目标值 ${target} 在数组中的索引是 ${result1}\n算法执行时间(毫秒): ${elapsedTime1}`);
    48. } else {
    49. console.log(`二分查找法2.0版本---------- 目标值 ${target} 未在数组中找到`);
    50. }

  • 相关阅读:
    ORB-SLAM2 ---- Tracking::CreateInitialMapMonocular函数
    jquery操作DOM对象
    深入浅出Python正则表达式:原理与应用
    分享券商量化交易接口申请流程
    一个简单的微信小程序表单提交样式模板
    确定性执行
    Vue 封装一个函数,小球原始高度不固定,弹起比例不固定、计算谈几次后,高度低于1米
    位运算(Bit Operation)
    计算机组成原理--存储系统
    第三十六章 使用 CSP 进行基于标签的开发 - 使用尽可能少的#server和#call调用
  • 原文地址:https://blog.csdn.net/lbcyllqj/article/details/134024820