基础算法合集-二分查找(三种写法)

数组如下:

[5,7,7,8,8,10]

问题:

返回有序数组中第一个>=8的数的位置,如果所有数都<8,返回数组长度

暴力做法:

遍历每个数, 询问它是否>=8 ?显然时间复杂度是O(n)

高效做法:

L和R分别指向询问的左右边界,即闭区间[L,R],M指向当前正在询问的数 (L=0, R=n-1)

5 7 7 8 8 10
L   M      R

观察上图我们很容易得出以下两个结论:

  1. 如果当前数是小于8, 由于数组是有序的, 那么当前数和当前数左边的所有数, 都是<8的
  2. 如果当前数是大于等于8, 由于数组是有序的, 那么当前数和当前数右边的所有数, 都是>=8的
如果当前数组长度是偶数的话,中间那个数的下标为(L+R)/2,
由于C++/JAVA中"/"是下取整的,所以此时的中位数是中间靠左的那个数
如果当前数组长度是奇数的话,中间那个数的下标为(L+R)/2,此时就是正中间的那个数

 第二次查询->将L更新为M+1的位置

5 7 7 8 8 10
      L M  R
对于为啥不能将L更新为M?
这是因为我们每时每刻都是在闭区间上进行处理的,如果把L改成M,那就是左开右闭区间了.
当数组中只有一个元素时,
 8
L,R
你把R更新成M,那不就死循环了吗
因为arr[4]=8>=8,所以继续执行第三次查询

 第三次查询->将R更新M-1

5 7 7 8 8 10
      LR
arr((L+R)/2)>=8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值