leetcode中的二分查找相关习题

leetcode中的二分查找相关习题

二分查找的必要条件就是有序,当说数组有序的时候就要考虑一下二分查找了

思想:二分查找就是在一个区间内通过求得该区间的中间值与目标值进行大小比较来缩小区间,区间不断缩小,其中间值很有可能就是目标值。

leetcode链接:

704.二分查找

image-20220306130936291

	
	//二分查找,条件:有序,元素不重复
    public int search(int[] nums, int target) {

        int left = 0;
        int right = nums.length - 1;    //定义区间的范围为[left,right]

        while (left <= right) {
            int mid = left + (right - left) / 2;    //防止溢出
            if (nums[mid] > target) {   //target在右区间,所以为[left,mid-1]
                right = mid - 1;
            }else if (nums[mid] < target) { //target在左区间,所以为[mid+1,right]
                left = mid + 1;
            }else {     //找到
                return mid;
            }
        }

        return -1;  //整个区间都搜索完了,还没找到
    }

leetcode链接:

35.搜索插入位置

image-20220306131931796

image-20220306131946916

根据题目条件很明显要使用二分查找

/**
     * 查找元素找到就返回下标,没找到就返回按序该插入的位置
     *  1.数组有目标值
     *  2.数组无目标值
     *      2.1 目标值在所有元素之前
     *      2.2 目标值在所有元素之后
     *      2.3 目标值在数组中的某一位置
     * @param nums  数组
     * @param target    目标值
     * @return
     */
    public int searchInsert(int[] nums, int target) {

        int left = 0;
        int right = nums.length - 1;    //区间[left,right]

        while (left <= right) {
            int mid = left + (right - left) / 2;

            if (nums[mid] < target) {     //target在右区间,所以为[mid+1,right]
                left = mid + 1;
            }else if (nums[mid] > target) {     //target在左区间,所以为[left,mid-1]
                right = mid - 1;
            }else {     //找到目标值
                return mid;
            }
        }

        //2.1 目标值在所有元素之前
        //2.2 目标值在所有元素之后
        // 2.3 目标值在数组中的某一位置
        return left;

    }

leetcode链接:

34. 在排序数组中查找元素的第一个和最后一个位置

image-20220306151832520

image-20220306151839426

有以下情况

  1. 是空数组
  2. 不是空数组但是数组里没有目标值
  3. 数组里有目标值
    1. findFirstPosition记录第一次出现目标值的位置
    2. findLastPosition记录最后一次出现目标值的位置
public int[] searchRange(int[] nums, int target) {

        if(nums.length == 0){   //空数组
            return new int[]{-1,-1};
        }

        int firstPosition = findFirstPosition(nums, target);
        if(firstPosition == -1){    //数组里没有目标元素
            return new int[]{-1,-1};
        }
        //一定有目标元素
        return new int[]{firstPosition,findLastPosition(nums,target)};
    }

    /**
     * 查找元素第一次出现的位置
     * @return
     */
    public int findFirstPosition(int[] nums, int target){

        int left = 0;
        int right = nums.length - 1;    //区间[left,right]

        while (left < right) {

            int mid = left + (right - left) / 2;
            if (nums[mid] < target) {   //target在右区间,mid及mid的左边一定不是 target 第一次出现的位置
                left = mid + 1;
            }else if (nums[mid] > target) {     //target在左区间,mid及mid右边绝对不可能是target
                right = mid - 1;
            }else {         //mid左边可能是第一次出现的位置
                right = mid;
            }
        }
        if(nums[left] == target){   //判断是否有目标值
            return left;
        }
        return -1;
    }

    /**
     * 查找元素最后一次出现的位置
     * @param nums
     * @param target
     * @return
     */
    public int findLastPosition (int[] nums, int target){

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

        while (left < right) {
            int mid = left + (right - left + 1) / 2;    //不加1会死循环
            if(nums[mid] < target){    //target在右区间,mid及mid左边绝对不可能是target
                left = mid + 1;
            }else if (nums[mid] > target) {     //target在左区间,mid及mid的右边不可能出现target
                right = mid - 1;
            }else {
                left = mid;     //mid的右边可能有最后一次target的位置
            }

        }
        return left;    //不用判断了,因为findFirstPosition中已经判断过了
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值