【Leetcode刷题笔记】01-二分查找的边界问题与区间的概念

二分易错点:边界问题

二分查找的难度并不是很大,但经常一写就废。因此整理一些自己经常遇到的坑,用于加强记忆。
二分查找常见的错误基本就是边界问题,常见的边界问题有如下几点:

  • 循环逻辑。用left<right还是left<=right。
  • 更新区间。更新区间时,middle要不要加一或者减一。

如果使用二分查找解决问题时,这两个地方经常出错,那就是对查找中区间的概念有些欠缺,因此处理不好边界问题。
练习题目:Leetcode704-二分查找
建议通过这个题目明晰边界问题与区间的概念之后,再进行深入的联系。

什么是区间

二分查找是在一个数组(nums)中找到与目标值(target)相等的元素的算法,效率比遍历比较要高。二分查找的查找过程到处都能找到资源,在此不多赘述,我们的重点放在区间上。
数组的长度是nums.length(),使用二分法时,我们通常会定义左右指针,这两个指针形成一个区间,我们每次在这个区间中寻找元素,这个区间通常是左闭右闭区间[left,right]或者左闭右开区间[left,right)
通常,在最开始定义左右指针的时候,我们会将左指针定义为0,右指针定义为数组长度或者是数组长度减一。右指针定义方式的不同,代表选择的区间方式不同,那么我们后续逻辑编写缩小范围以及确认循环逻辑时,就需要按照已定的区间逻辑进行编写。逻辑不一致,就会导致代码出现问题。

//左闭右开.
int left = 0;
int right = nums.length();

//左闭右闭.
int left = 0;
int right = nums.length() - 1;

左开也可以写二分法,但左开不是二分常用的逻辑,在此也不多赘述。

区间选择的不同给二分带来的影响

区间的选择为什么会给二分后来的逻辑带来影响呢?因为选择区间的时候我们定义了一条规则:区间的边界是否需要进入逻辑循环。这里就影响代码中的两个点:

  1. 循环条件的判断。左右节点相等时,是否需要进入循环。
  2. 新区间的判断。循环条件的判断已经确定,所以新区间应当按照既定的规则进行边界的判定,与最开始指定左右节点区间时,保持一致。

循环条件判断

当数组长度为1(或者缩小到长度为1时),我们需要将数组中的元素与目标元素进行对比,因此需要进入循环。
左闭右开区间中[left,right),只有一个元素时,左指针比右指针小1。while的循环条件不论是left<=right还是left<right都可以进入循环,但是如果选择了错误的区间left<=right,如果数组中没有匹配的项,就会陷入死循环。因为右指针不可能小于左指针。
左闭右闭区间中[left,right],只有一个元素时,左指针与右指针相等。如果想要进入循环,while的循环条件应该是left<=right。如果没有等号,则不进入循环,明明可以匹配成功,却显示匹配失败的结果。

新区间的判断

当我们定义完区间,以及符合区间逻辑的循环判断条件后,需要注意的点就是缩小区间时,新区间的判断。当缩小数组长度时,如果数组的边界与定义的判断逻辑不符,轻则多进行一次循环,重则找不到对应的数据。
我们每次进行区间的缩小,都会改变左右指针之一。两种区间之间的共同点是左闭,当目标值target大于nums[middle]的数据时,左指针通常可以改变为middle+1,因为middle的值已经经过判断,没必要再进行判断。
接下来只讨论右边区间的不同引起的代码的变化,以及不遵循这样的逻辑可能会带来的后果。
左闭右闭区间中,目标值target小于nums[middle],改变右边界时,右指针最好等于middle-1,因为middle的值已经经过判断,没必要再进入循环。改为middle无非就是可能多进入一次循环。
但是,在左闭右开区间中,改变右边界时,右指针只能等于middle,因为左闭右开区间中,右指针指向的元素本身就不参与计算,如果此时右指针等于middle-1,元素nums[middle-1]就没有跟target进行比较,可能会漏掉我们需要找到的元素。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一张话痨帆

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

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

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

打赏作者

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

抵扣说明:

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

余额充值