二分查找

前提:有序数组
时间复杂度:log2n (每次分一半,所以对N求以2为底的对数就是时间复杂度)
注意一点:向右找left = mid+1;向左找right = mid-1;
举个简单例子:int a[]={1,2,3,4,5,6,7,8,9,10} 查找11.
然后我们按步骤来,来看看都会有哪些情况:
范围:left:左边第一个下标,right:右边最后一个下标
中间数下标:(left+right)/2
第一次:下标范围0,9,中间数下标(0+9)/2= 4,中间数是:5 ,结果:要找的数比5大 ,进入右空间
第二次:下标范围5,9,中间数下标(5+9)/2= 7,中间数是:8 ,结果:要找的数比8大 ,进入右空间
第三次:下标范围8,9,中间数下标(8+9)/2= 8,中间数是:9 ,结果:要找的数比9大 ,进入右空间
第四次:下标范围9,9,中间数下标(9+9)/2= 9,中间数是:10 ,结果:要找的数比10大 ,进入右空间
第五次:下表范围10,9,不符合left<=right,结束。

当然还有一种最简单的结束查找的情况就是,中间数就是我们要找的数,那也结束了。

对了,上面给的数列偶数个,那奇数个呢?
来看看吧,int a[] = {1,2,3,4,5,6,7,8,9} 查找9
第一次:下标范围0,8,中间数下标(0+8)/2=4,中间数是:5,结果:要找的数比5大 ,进入右空间
第二次:下标范围0,8,中间数下标(5+8)/2=6,中间数是:7,结果:要找的数比7大 ,进入右空间
第三次:下标范围7,8,中间数下标(7+8)/2=7,中间数是:8,结果:要找的数比8大 ,进入右空间
第四次:下标范围8,8,中间数下标(8+8)/2=8,中间数是:9,结果:找到结束。

但是,你会发现在查找11的时候其实结果已经非常明显了,我们要找的数很明显已经大于了a数组中最大的数了,但我们还这样查找了一通,是非常不理智的,所以我们可以在查找前先判断一下我们要找的数是不是在我们查找的范围内,也就是和下标为left的数和下标为right的数比较一下,看是不是在范围内。
还有相等优化即第一个元素和最后一个元素相等则返回。
还有先判断第一个和最后一个元素是否为要找元素(个人感觉这个并没有很好)

结束情况:
范围超出,
找到结束,
left>right结束。

最后是我的一个实现(递归和非递归):
测试:所有a[]里面的数据和-1,111数据答案都没错。

import java.util.Scanner;

/**
 * Created by 96274 on 2018/11/18.
 */
public class half {

    //递归
    public static int binarySearch(int t , int left, int right,int a[]){
        //System.out.println("left="+left+",right="+right);
        if(t>a[right] || t< a[left]){
            return -1;
        }
        if(left<=right){
            int mid = (left+right)/2;
            if(a[mid] == t)
                return mid;
            if(t>a[mid]){
                return binarySearch(t,mid+1,right,a);
            }else{
                return binarySearch(t,left,mid-1,a);
            }
        }
        return -1;
    }

    //非递归
    public static int binarySearch(int t ,int a[]){
        int left = 0,right = a.length-1;

        if(t>a[right] || t< a[left]){
            return -1;
        }
        while(left<=right){
            int mid = (left+right)/2;
            if(a[mid] == t)
                return mid;
            if(t>a[mid]){
                left = mid+1;
            }else{
               right = mid-1;
            }
        }
        return -1;
    }

    public static void main(String[] args){
        int a[] = {1,2,3,3,5,6,7,8,9,19,20};
        int t ;
        while(true){
            Scanner sc = new Scanner(System.in);
            t = sc.nextInt();
            int x = binarySearch(t,a);//binarySearch(t,0,(a.length-1),a);
            System.out.println(""+x);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值