二叉算法详解

文章详细介绍了如何使用二分查找算法在有序数组中寻找特定数值的左边界和右边界。在标准二分查找的基础上,针对左边界和右边界问题进行了优化,分别调整了搜索区间的移动方式,以避免数组越界并处理不存在目标值的情况。通过这种方式,可以更精确地定位到目标值在数组中的位置范围。
摘要由CSDN通过智能技术生成

二叉查找

我们学习的时候一般使用这个查找算法,在有序数组中(递增递减都行)来查找某一个数

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

// int mid=left+(right-left)/2; 这样的操作和左右相加再除以二 等价,但是有效的防止了left和right相加过大,导致的溢出情况

但是实际题目中,并不会直接考你二分查找算法怎么写,而是考察你有多个相同的数,要求得到索引最小或索引最大的,这就是左边界问题和右边界问题。

求左边界

//这些题解中的函数都是一个,只是具体方法不同,在下面的代码中,我就只写出函数体了
int left=0;
int right=nums.size();
while(left<right)
        {
            int mid=(left+right)/2;
            if(nums[mid]==target) right=mid;
            else if(nums[mid]<target) left=mid+1;
            else if(nums[mid]>target) right=mid; 
        }
        if(left==nums.size()) return -1;
        else if(nums[left]==target)  return left;
        else if(nums[left]!=target)  return -1;

首先 while判断语句中,用大于或者大于等于都行,只是具体细节方面需要调整,个人喜欢不加上等号,所以用的是不加上等号的版本。

不加上等号,那么while循环的截止条件是left==right 那么left能取到的范围是[0,nums.size()]左右都能取到,但是因为我们求得是索引,所以到不了nums.size();

所以在后面,得加上补丁防止数组越界

if(left==nums.size())  return -1;

若我们查找得数组中不存在这个值的话,也需要进行一次判断

else if(nums[left]==target)  return left;
else if(nums[left]!=target)  return -1;

求右边界

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

为什么最后返回的是left-1?

因为在中值和目标值相等之后,left又进行加一操作,所以就可能导致nums[left]!=target了

为了防止第一个就是想要查找的值,即数组越界问题,所以我们需要进行一次判断,防止越界

补丁为:

 if(left-1<0) return -1;

总结

这个方法,在二分后分成的数组是[left,mid], [mid+1,right]

和一般的版本不同,用这种分法是为了更好的找到边界问题

求左边界和求右边界方法差不多,唯一的区别是

求右边界时:

nums[mid] == target 时,不要立即返回,而是增大「搜索区间」的左边界 left,使得区间不断向右靠拢,达到锁定右侧边界的目的。

求左边界时:

nums[mid] == target 时,不要立即返回,而是增大「搜索区间」的右边界right,使得区间不断向左靠拢,达到锁定左侧边界的目的。

注意:

注意「搜索区间」和 while 的终止条件,如果存在漏掉的元素,记得在最后检查

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值