二分查找-LeeCode相关题目

本文介绍了如何使用二分查找算法在有序整型数组中查找目标值及其出现位置,包括左右边界查找方法,并通过LeetCode题目实例演示了`binary_search`和`searchRange`的实现。重点在于理解查找过程中的终止条件调整和结果整合。
摘要由CSDN通过智能技术生成

第一题:

题目要求

704 二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/binary-search

// 二分查找,有序数组中是否存在
public int BinarySearch(int[] arr, int target) {
    int L = 0;
    int R = arr.length - 1;
    while (L <= R) {
        // int mid = L + ((R-L)/2); 除以2: N/2  相当于 带符号右移1位: N>>1
        int mid = L + ((R - L) >> 1);  // 相当于 (L+R)/2
        if (arr[mid] == target) {
            return mid;
        } else if (arr[mid] < target) {
            L = mid + 1;
        } else {
            R = mid - 1;
        }
    }
    return -1;
}

效果:

 

第二题

题目要求:

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

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

(1)给定目标值在数组中的 开始位置 :

也就是找有序数组中 target第一次出现的位置:

// 找 等于target的 最左位置  二分
public int searchLeftEqual(int[] arr, int target){
    int L = 0;
    int R = arr.length-1;
    int leftIndex = -1; // 一开始假设为 -1  表示没有target这个数
    while (L <= R){
        int mid = L + ((R-L) >> 1);  //  相当于 (L+R)/2
        if (arr[mid] == target){  // 找到一个等于target的数
            leftIndex = mid; // 位置记录下来
            R = mid -1; // 但是还没有结束,继续在左边部分查找 还有没有等于target的数
        }else if (arr[mid] > target){
            R = mid -1;  // 中间位置的数 大于target,说明应该去 左边部分查找
        }else {
            L = mid +1;  // 中间位置的数 小于target,说明应该去 右边部分查找
        }
    }
	// 若是数组中不存在目标值target,leftIndex就从不会变,也就是仍然为初始值-1
    // 若是数组中存在目标值target,leftIndex 必然会被重新赋值:leftIndex = mid
    return leftIndex;  
}

(2)给定目标值在数组中的 结束位置

也就是找有序数组中 target 最后一次出现的位置:

// 找 等于target的最右位置  二分
public int searchRightEqual(int[] arr, int target){
    int L = 0;
    int R = arr.length-1;
    int rightIndex = -1; // 一开始假设为 -1  表示没有target这个数
    while (L <= R){
        int mid = L + ((R-L) >> 1);
        if (arr[mid] == target){
            rightIndex = mid; // 位置记录下来
            L = mid +1; // 但是还没有结束,继续在右边部分查找 还有没有等于target的数
        }else if (arr[mid] > target){
            R = mid -1;
        }else {
            L = mid +1;
        }
    }

    return rightIndex;
}

(3)结合 两个函数得出最后结果

public int[] searchRange(int[] nums, int target) {
    int[] pos = new int[2];
    pos[0] = searchLeftEqual(nums, target);
    pos[1] = searchRightEqual(nums, target);
    return pos;
}

效果展示:

 

总结:对比最左和最右,方便记忆

其实只有一个位置不同 (不考虑leftIndex或者rightIndex,它俩作用其实都一样,名字不同而已),就是找到target时:

  • 一个是在左侧继续查找,所以需要改变 R

  • 一个是在右侧继续查找,所以需要改变 L

 

要注意的是:while 循环里条件 ( L <= R

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值