数据结构与算法---二分法 超详细解,保证你能看懂!!!!!

二分法不难,看完这篇文章,你必懂。

假如我们遇到了一道算法题,要求我们从数组A=[a,b,c,d,e] 里找到d,那通常我们会逐个遍历,遍历a,b,c,d一共需要对比4个数字才能找到d。

那如果使用二分法呢?如何使用二分法?

1.首先我们设置两个指针指向该数组的开头和结尾,
L指向开头,R指向结尾。
在这里插入图片描述

2. 我们找到两个指针的中间点mid,(此时L为1,R为5,通常情况下mid=(L+R)/2)=3
在这里插入图片描述
3. 对比mid和我们所需要找的数之间的大小,我们要找的是D显然C<D,此时将L挪到mid的位置,然后算出新的mid。
(如果本题要找的是B,同理,mid所指向的C大于B,则将R放到mid的位置然后算出新的mid。)
在这里插入图片描述
4. 重复上面的步骤继续对比mid所指向的数是不是等于我们要找的数。mid=D 是我们要找的数,结束。

5. 如果L都移动到R的右边了还没找到我们要的数,则可以判断,这堆数里没有我们要找的数。

上面就是二分法的基本思想,可以看到,如果使用普通方法找D我们需要对比A,B,C,D 四次,而使用二分法我们只对比了C和D 2次就找到了。

杂谈:
关于二分法还有相当多的变种,现在讲必然会乱到炸。比如移动的时候不是直接将R或者L放到mid 而是放到mid+1 或者mid-1。。而在L和R的设置上也有开闭区间等多种,在mid计算上也有向下向上取整的问题。

这些都不要管!!!!!!!!!!!!!!!!!!

只需要懂得上面的思想,然后拿题去一点一点做去试,一开始必然都是错误,返回去继续想一遍流程,再改,这些都会融会贯通的。

怎么去试呢?

下面我用一个例题,让你从此以后彻底掌握二分法。(其他算法那也可以用此方法融会贯通)。

例题:

这里使用的例题:leetcode 374题。
题目给了一堆数共n个。 其中只有一个是正确的数,你要猜一下这个正确的数是几。
只不过你猜的这个数要通过一个函数去判断你猜的对不对。
如果函数返回了 1 说明正确的数比你猜的数要大。
如果函数返回了 -1 说明正确的数比你猜的数要小。
如果返回了0 说明你猜对了。

那么按照上面的算法思想写一下代码。
设置L和R指向头和尾 那就是

L = 1
R = n

如果L一直在R左边,那就一直算mid。

while l < r:
	 mid = (l+r) // 2

每次算出来的新mid,调用函数看他是不是正确的数。

	if guess(mid) == 0:
		print(‘这是正确的数’)
    elif guess(mid) == -1:
        r = mid
    elif guess(mid) == 1:
        l = mid

我们吧上面的代码拼接起来(别忘了print改成return)
拿去leetcode跑一遍测试用例发现,当n=2,所要找的数=2时。在这里插入图片描述
超时了。。。。。。。。
超时的原因肯定是while没有出来。于是我们将 n=2 ,正确的数=2带入到上面的错误程序中。

首先
L = 1
R = 2
算出mid =(L+R)/ 2 = 1

在这里插入图片描述
此时发现L和mid都指向1,显然我们要找的2是比1要大的,所以调用的guess函数返回了 1 执行代码:

elif guess(mid) == 1:
        l = mid

本来mid和L就已经指向同一位置了。执行了这段代码等于什么也没干,就这样一直死循环在while里导致程序运行超时。

这时候怎么办呢,我们要找的明显是2。

此时使用二分法的变种(实际就是根据题的需要改变二分法的写法).

我们可以将 L = mid 改为 L = mid +1 这样L就会指向2。
改动代码:

elif guess(mid) == 1:
        l = mid +1  

还是这个图, 当函数guess返回1的时候 L = mid L和mid都是指向1.程序死循环,而我们改成了 L = mid + 1 ,则此时L会指向 R所指的位置。
在这里插入图片描述
在这里插入图片描述
此时进入下一次while循环发现L<R 已经不满足无法在进入循环,程序失败。所以将循环退出条件改为 L <= R。进入循环,计算新的mid=2.判断函数返回0,程序正确结束。拿去leetcode进行测试。
在这里插入图片描述
测试通过。掌握基本思想,通过例题逐步调试写出正确二分法的变种,更利于学习算法思想。

第一次这样手写讲解算法,如果有不懂的地方或者讲解有错误,留言给我,互相进步。

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

深度不学习!!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值