704.二分查找

思路

核心

二分查找,通过条件的判断,传入整个数组的一半,并且去看这部分数组的中间值是否满足要求,循环此过程,直到找到目标值的下标。

图解

准备数组

准备一个数组,这个数组满足下面两个条件:

  • 有序
  • 无重复

有序,才能进行“大了还是小了”的条件判断。

无重复,返回的下标才是唯一的。

第一次传入数组

第一次传入数组,没有进行过条件判断,于是传入整个数组

条件判断

由上图所示,mid指向的数字小于target=9

那么,就需要去整个数组的右边部分进行查找

再次传入数组

在这次传入数组中,end的位置没有变化

start的位置变为 原来的mid 的后一个。

mid此时指向target=9,直接返回

终止条件

从上面分析的过程中可以知道,要一次又一次的传入数组,进行处理

那么,什么时候停止传入呢?

在传入数组的过程中,start和end指针会不断靠近。

会不会是当start和end处于某种关系时,循环就停止呢?

考虑这种情况,target=15

再进行一次循环,会变成下面这样

start和end相等了。

这就是中止条件

[start,end]这个区间已经缩到最小,但是还没找到,就是真的找不到了

区间不变

这道题比较难的就是要保证区间的不变性。

区间不变,有两种选择:

  • [start,end] 前闭后闭
  • [start,end) 前闭后开

对于区间的选择不同,对所有有判断条件的写法是不同的。

在本题中,就是指while、if-else中的判断条件。

[start,end]

while

两个都是闭区间,start=end才有效

判断条件

 

上面的情况中,我们希望下一次传入数组[3,5]

所以start=mid+1

[start.end)

上面的情况,我们希望下一次传入数组为[0,1]

因为传入的是[ )这种形式

为了传入[0,1],其实需要传入[0,2),因为区间是闭区间,只有这样才能把右端的1取上

所以end=mid-1

1刷

var search = function(nums, target) {
    var start = 0;
    var end = nums.length;
    while(start < end) {
    var mid = start + ((end - start) >> 1);
        if(nums[mid] > target) {
            end = mid;
        }else if(nums[mid] < target) {
            start = mid + 1;
        }else {
            return mid;
        }
    }
    return -1;
};
 

与正解对比

  • 区间不变性没考虑
  • 跳出while循环的条件

问题点

  1. js中的除法问题
  2. 开闭区间的问题

除法的问题

js中,5 / 2 得到的是2.5

而在Java中 5 / 2得到的是2

如果要像Java这样用除法,得带个向下取整的floor方法。

或者用位运算

mid = Math.floor((start + end) / 2);
mid = left + ((right - left) >> 1);

开闭区间

什么时候需要考虑区间的开闭?

答:取数组的子数组进行处理时、确定循环条件时

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值