二分法pro max版

文章介绍了二分法的基本概念,包括如何在有序数组中查找特定元素。它强调了在while循环中使用小于等于号的原因,以及在找不到目标元素时调整left和right边界的方法。文章还讨论了当数组中存在重复值时二分查找的局限性,并提供了扩展的二分查找算法,用于找到目标元素的最左侧和最右侧边界。
摘要由CSDN通过智能技术生成

二分法pro max版

什么是二分法

简单来说,就是在一堆有序数组中查找特定元素的搜索算法。大致思路如下:
(1)从中间元素开始查找,若等于target,则返回,否则执行下一步;
(2)若target 大于/小于 中间元素值,分别缩进左/右边界,则在右/左半区间继续查找,执行(1)中操作;
(3)若数组为空,则表示找不到该目标元素target,返回-1。

最基本的二分查找

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

下面回答几个问题:

1.为什么 while 循环的条件中是 <=,而不是 <

在while循环中,使用<=是因为需要将查找范围缩小至只有一个元素时,也需要继续比较。如果只使用<,会漏掉最后一个元素的比较。因此,使用<=可以确保最后一个元素也能够被比较。

2.为什么left = mid + 1,right = mid - 1?

本算法的搜索区间是两端都闭的,即[left, right]。当我们发现索引mid不是要找的目标元素时,下一步应该去搜索哪里呢?当然是去搜索[left, mid-1]或者[mid+1, right],因为mid已经搜索过,应该从搜索区间中去除。

3.算法存在的不足

当查找元素的数组中存在重复的值,而我们想要获得最左侧或者最右侧边界的索引,这显然是无法办到的。例如 nums = [1,3,4,5,5,5,6] ,target为5时,此时返回的索引值是3,当我们想要获得最左侧或者最右侧的索引时,是显然无法处理的。

寻找最左侧边界的索引

int left_bound(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 缩紧右侧边界
            right = mid - 1;
        }
    }
    // 判断 left 越界情况
    if (left >= nums.length || nums[left] != target)
        return -1;
    return left;
}

我们需找到 target 的最左侧索引,当 nums[mid] == target 时,不要立即返回,而要收紧右侧边界以锁定左侧边界。

寻找最右侧边界的索引

int right_bound(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 缩紧左侧边界
            left = mid + 1;
        }
    }
    // 判断 right 越界情况
    if (right < 0 || nums[right] != target)
        return -1;
    return right;
}

我们需找到 target 的最右侧索引,当 nums[mid] == target 时,不要立即返回,而要收紧左侧边界以锁定右侧边界。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

想什么起什么~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值