关于二分查找中的一些问题

相信对于学习编程每一个同学来说,肯定都知道二分查找算法,并且写过相应的测试代码,那么我们先来说一下二分查找的的优缺点吧。

这大家都很清楚,优点呢就是二分查找是折半查找,每次查找都可以排除一半的数据,这应用在一个大数据量的查找中,效率是非常高的。当然了,缺点也很明显,就是二分查找的前提是,查找的数据一定是经过排序的,无论是升序还是降序,这会打乱原先的数据的位置。所以在实际情况中,还请大家仔细考虑,是否需要进行二分查找。

话不多说,我们直接上代码。

public class Main{

    public static int getPos(int[] A, int n, int val) {

        return indexOf(A,val,n);
    }

    public  static int indexOf(int[] a,int val,int n){
        int low=0;
        int high = n-1;
        while(low < high) {
            int middle = (low+high)/2;
            if(val > a[middle]) {

                low=middle+1;
            }else if (val == a[middle]) {

                //若查找到,直接返回元素的索引
                return middle;
            } else {

               high=middle-1;
            }
        }
        //未找到,返回-1
        return -1;
    }

    public static void main(String[] args)
    {
        int[] a={1,4,7,9,15}; //数组必须是经过排序的
        int n=a.length;
        int val=1;
        System.out.println(getPos(a, n, val));
    }
}

  相信大家对这种二分查找应该很熟悉,当然输出结果为0.

现在我们来考虑另外一种情况,就是元素不是递增或者递减的,而是非递增或者非递减的情况,什么意思呢,就是说数组中包含相同的元素,这种情况下我们想的是返回元素第一次在数组中出现的位置,那么结果是这样吗?让我们测试一下。

修改数组元素为[1,3,3,4,5],查找元素为3的索引

结果为:。结果并不和我们想的一样,首先我们来分析一下原因。折半查找首先会从中间元素开始查找,寻找特定的元素,所以靠近中间位置的元素首先会被找出来。所以现在看来,出现这个问题也不是很意外了,那我们应该怎么解决呢。

解决思路如下:当寻找出我们要的那个元素之后,应该继续向索引小的一方继续查找,若存在和当前值相等的元素,则返回索引值小的元素,若不存在,直接将当前索引值返回即可。思路很简单,关键在于代码实现。那么接下来,我们看代码。

public class Test6 {

    public static int getPos(int[] A, int n, int val) {

        return indexOf(A,val,n);
    }

    public  static int indexOf(int[] a,int val,int n){
        int low=0;
        int high = n-1;
        while(low < high) {
            int middle = (low+high)/2;
            if(val > a[middle]) {
                low=middle+1;
            }else if (val == a[middle]) {
                //主要就是改进这段代码
                int temp=middle;
                //先判断索引值的目的是防止数组越界异常
                while(temp > 0 && a[--temp] == val)
                {
                    middle--;
                }
                return middle;
            } else {
               high=middle-1;
            }
        }
        //未找到,直接返回-1
        return -1;
    }

    public static void main(String[] args)
    {
        int[] a={1,3,3,4,5}; //数组必须是经过排序的
        System.out.println("数组元素为:[1,3,3,4,5]");
        int n=a.length;
        int val=3;
        System.out.println("元素3的索引值:"+getPos(a, n, val));
    }
}
运行结果为:
数组元素为:[1,3,3,4,5]
元素3的索引值:1

代码底部有运行结果,可以看出这个结果才是我们想要的。以上就是我关于二分查找的一些总结,希望对你们有帮助。

通过这个例子,我们可以总结出:解决问题的时候,一定要考虑清楚所有的细节,也是出现相等元素只是一个小问题,但就是这种小问题,有可能会困扰到我们,所以说一些细枝末节我们才不能放过。

时间: 2024-08-25 14:23:25

关于二分查找中的一些问题的相关文章

二分查找中的死循环

二分算法是我们经常会用到的一个算法.它是分治法的一个应用.不过,虽然他写起来貌似很简单,但是却很容易写错.下面我们讨论一下二分的死循环问题.(这里讨论的是整数的二分问题,浮点数的二分不容易死循环) 1.查找的元素确定,值唯一或者不存在 这种情况等下,我们的流程分为三个分支:(相等.小于.大于).这类不容易死循环,代码如下: if ( data[mid] == key ) return mid; if ( data[mid] > key ) r = mid-1; else l = mid+1; 2

HDOJ2141(map在二分查找中的应用)

#include<iostream> #include<cstdio> #include<map> #include<algorithm> using namespace std ; #define M 500 + 10 int a[M] ; int b[M] ; int c[M] ; int d[M] ; int l ; int n ; int m ; map <int , bool > Map ; void Marge() { for(int

二分查找的改进--差值查找

差值查找 在二分查找中,我们每次比较都可以排除一半的数据量,这个已经是很高效了.如果利用关键字本身的信息,每次排除的数据量充分依赖于关键字的大小,则查找会更高效,这就是差值查找的思想. 下面通过示例代码,比较二分查找和差值查找的不同,在不同中领略差值查找的改良之处. #include <stdio.h> #include <stdlib.h> int InterSearch(int *array, int n, int key) { if (array && n &

检索算法——二分查找

如果要查找的数据是有序的, 二分查找算法比顺序查找算法更高效. function insertionSort(arr) { var temp, inner; for ( var outer = 1; outer < arr.length; ++outer) { temp = arr[outer]; //选中一个值作为临时值,使得其前面的数依次与它进行比较 inner = outer; while (inner > 0 && (arr[inner - 1] >= temp)

二分查找算法(递归,循环)

二分查找算法是在有序数组中用到的较为频繁的一种算法,在未接触二分查找算法时,最通用的一种做法是,对数组进行遍历,跟每个元素进行比较,其时间为O(n).但二分查找算法则更优,因为其查找时间为O(lgn),譬如数组{1, 2, 3, 4, 5, 6, 7, 8, 9},查找元素6,用二分查找的算法执行的话,其顺序为:    1.第一步查找中间元素,即5,由于5<6,则6必然在5之后的数组元素中,那么就在{6, 7, 8, 9}中查找,    2.寻找{6, 7, 8, 9}的中位数,为7,7>6,

二分查找 : 那个隐藏了 10 年的 Java Bug

一个偶然的机会,我想起以前还在谷歌上班的时候,有时候大家会在饭桌上讨论最新想出来的一些面试题.在众多有趣又有难度的题目中,有一道老题却是大家都纷纷选择避开的,那就是去实现二分查找. 因为它很好写,却很难写对.可以想象问了这道题后,在5分钟之内面试的同学会相当自信的将那一小段代码交给我们,剩下的就是考验面试官能否在更短的时间内看出这段代码的bug了. 二分查找是什么呢,这个不只程序员,其他很多非技术人员也会.比如我想一个1到100以内的数,你来猜,我告诉你每次猜的是大了还是小了,你会先猜50,然后

详解二分查找算法

我周围的人几乎都认为二分查找很简单,但事实真的如此吗?二分查找真的很简单吗?并不简单.看看 Knuth 大佬(发明 KMP 算法的那位)怎么说的: Although the basic idea of binary search is comparatively straightforward, the details can be surprisingly tricky... 这句话可以这样理解:思路很简单,细节是魔鬼. 本文就来探究几个最常用的二分查找场景:寻找一个数.寻找左侧边界.寻找右侧

STL中的二分查找———lower_bound,upper_bound,binary_search

关于STL中的排序和检索,排序一般用sort函数即可,今天来整理一下检索中常用的函数——lower_bound , upper_bound 和 binary_search . STL中关于二分查找的函数有三个lower_bound .upper_bound .binary_search .这三个函数都运用于有序区间(当然这也是运用二分查找的前提). Tips:1.在检索前,应该用sort函数对数组进行从小到大排序.     2.使用以上函数时必须包含头文件:#include < algorith

动态数组,数组初始化,数组内存释放,向数组中添加一个元素,向数组中添加多个元素,数组打印,顺序查找,二分查找,查找数组并返回地址,冒泡排序,改变数组中某个元素的值,删除一个数值,删除所有,查找含有

 1定义接口: Num.h #ifndef_NUM_H_ #define_NUM_H_ #include<stdio.h> #include<stdlib.h> /************************************************************************/ /*数组的结构体类型                                                    */ /*******************