小洛算法--二分算法

文章介绍了二分算法的概念,强调其在有序数组中查找元素的高效性,时间复杂度为O(logn)。文中通过红蓝二分法解释了如何避免边界问题,并展示了Python内置的`bisect_left()`和`bisect_right()`函数在查找元素位置时的使用方法。
摘要由CSDN通过智能技术生成


二分是什么可以干什么?

二分是一种常用的算法技巧,用于在有序数组或有序序列中查找某个元素的位置。

二分算法的基本思路是将查找区间不断缩小,直到找到目标元素或者确定目标元素不存在。具体实现方式是先确定查找区间的左右边界,然后计算中间位置的元素值,如果该值等于目标值,则找到目标元素;如果该值大于目标值,则说明目标元素应该在左半部分查找,反之则在右半部分查找。不断缩小查找区间,直到找到目标元素或者确定目标元素不存在。

于是我们引入红蓝二分的思想来更好的引入二分

一、学习二分思想

二分算法的时间复杂度为 O(log n),其中 n 是数组或序列的大小,相对于暴力枚举的时间复杂度 O(n) 来说,具有更好的时间效率

使用条件和难点

尽管二分算法看起来简单,但实际上它也有一些使用条件和难点:

  1. 最痛苦的莫过于边界条件
    在实现二分算法时,边界条件是非常关键的。边界条件包括搜索区间的起点和终点,以及中间元素的计算方式。如果边界条件不正确,就可能导致算法出现错误或进入死循环。

  2. 数组必须有序
    由于二分算法的核心思想是逐步缩小搜索区间,所以必须保证数组是有序的。如果数组无序,则需要先进行排序,这将增加算法的复杂度。

  3. 最重要的是能看出它能用二分(状态转移设计):
    如:动态规划+二分 leetcode.300 这个一般人还真的不知道怎么能用二分,当初我就在想他们的脑子的是什么做的!

题目引入

红蓝二分法
先来简单的二分
现在我要在一个数组中找数:

list_num = [ i for i in range(0,100,2)]

# 找22在这个数组的哪里,或者22有没有在这个数组里面
left = -1
right = len(list_num)
while left+1!=right:
	mid = (left+right)//2
	if list_num[mid]<=22:
		left = mid
	else:
		right = mid
return left

这就是一个经典的红蓝二分法写出来的,看他的条件left+1!=right,于是我们不会出现left和right相交的情况。
而我们的答案却已经放入了left 和 right 里面了

下面我们来详细解说什么是红蓝二分法
left, right 就是红蓝二分的边界,如名字一样一个是右边的边界,一个是左边的边界。边界不会相交,而只有满足条件left+1==right 时才会相邻。也就是While循环退出的时候

然后是初始left, right时初始值填的是什么:
left:-1
right:len(list)
这样我们就不用去想边界的问题了,应为要么list的区域全被left占领,要么就是被right。
而我们通过红蓝二分的方法很巧妙的绕开了二分的边界问题
五点七边up的视频素材
在这里插入图片描述
大家看完应该对二分的很多题都可以解了
解下来我们主要的是去理解状态转移的设计,能写出二分不是什么要的是你能看出这能使用二分。很多算法都是不是你能写,而是你能看出它能用!

二、Python内置的二分函数

这个库是真的好用,而且还是内置的在算法竞赛的时候效果很好

Python中的二分函数可以使用标准库bisect来实现。bisect模块提供了两个函数:bisect_left()和bisect_right()。这些函数使用二分查找算法在有序序列中查找指定元素的位置。

这两个函数的区别在于,当有多个相同的元素时,bisect_left()函数返回第一个出现的位置,而bisect_right()返回最后一个出现的位置。

import bisect

lst = [1, 3, 4, 4, 4, 6, 8, 9]
x = 4

使用 bisect_left() 查找 x 的位置

idx_left = bisect.bisect_left(lst, x)
print("bisect_left(): ", idx_left)

使用 bisect_right() 查找 x 的位置

idx_right = bisect.bisect_right(lst, x)
print("bisect_right(): ", idx_right)
输出:
bisect_left():  2
bisect_right():  5
在上面的示例中,列表lst中有多个值为4的元素。
bisect_left()函数返回第一个出现的位置2,
而bisect_right()函数返回最后一个出现的位置5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值