二分查找及相关题解析(Java)

定义

二分查找,又称折半查找法
基本思路:

找到有序序列的中位数mid,与目标值k进行比较,根据比较结果,进一步缩小查找范围。

限制条件

  • 必须是顺序表

    如果是链式存储,不能直接获取中间的数

  • 必须有序

    需要确定指针移动的方向,与中间值进行比较后,需要确定指针移动的方向。确保,一边比另一边大

  • 查找对象只能是一个

代码

public class BinarySearch {

    private static int[] nums = new int[]{0,1,2,3,4,4,4,5,6,7};

    public static void main(String[] args) {
        System.out.println(method1(nums,0));

        System.out.println(method2(nums,0));
    }

    /*非递归*/
    private static int method1(int[] nums, int target){
        //定义指针
        int left = 0;
        int right = nums.length - 1;
        while(left <= right){//循环条件,当相等时,也可能是最终结果
            int mid = (left+right)/2;
            if(nums[mid] == target){
                return mid;
            }else if(nums[mid] > target){
                //mid 位置的值肯定不是目标值,所以--
                right = --mid;
            }else if(nums[mid] < target){
                //mid 位置的值肯定不是目标值,所以++
                left = ++mid;
            }
        }
        return -1;
    }

    /*递归*/
    private static int method2(int[] nums,int target){
        return recursion(nums, target, 0, nums.length-1);
    }

    private static int recursion(int[] nums, int target, int left, int right) {
        //退出条件
        if(left > right){
            return -1;
        }
        int mid = (left + right)/2;
        if(nums[mid] == target){
            return mid;
        }else if(nums[mid] > target){
            return recursion(nums,target,left,mid-1);
        }else{
            return recursion(nums,target,mid+1,right);
        }
    }
}

举一反三

当有序序列可重复,且需要寻找的元素在序列中有多个时,依据普通的二分查找,找到的元素是随机的。

问题1: 如何找到第一个出现的元素?

public class BinarySearch2 {

    private static int[] nums = {0,4,4,4,4,4,4,4,5};

    public static void main(String[] args) {
        System.out.println(method1(nums,4));
    }

    public static int method1(int[] nums, int target){

        int left = 0;
        int right = nums.length - 1;

        while(left < right){
            int mid = (left + right) /2;
            //当中间值与目标值相等时,不能确定是不是第一个,但可以确定,数组右边一定不是,所以将右指针指向mid
            if(nums[mid] >= target){
            	//没有等号,因为中间值可能就是所需要的结果
                right = mid;
            }else{
                left = mid+1;
            }
        }
        //当left == right 的时候遍历完,只需要判断当前值是不是目标值即可
        if(nums[left] == target){
            return left;
        }

        return -1;
    }
}

问题2: 一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

来自leetcode 题目链接

分析:

  • 有序顺序表查找,可以使用二分查找。
  • 所有数字唯一,且只有一个不在数组中

    正常不缺失的数组,数组下标等于对应的值,
    当缺失了一个数字后,
    当前数字以及其后面的数字大于数组下标

public class BinarySearch3 {

    private static int[] nums = {0,1,2,3,4,6,7,8};

    public static void main(String[] args) {
        System.out.println(method1(nums));
    }

    private static int method1(int[] nums){

        int left = 0;
        int right = nums.length -1;
        while(left < right){
            int mid = (left + right) /2;
            if(nums[mid] == mid){
                left = mid +1;
            }else if(nums[mid] > mid){
                right = mid;
            }
        }

        if(nums[left] > left){
            return left;
        }

        return -1;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RwTo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值