1.关于左右
1.1 值存在于列表
from bisect import bisect,bisect_left,bisect_right
list_positive = [0,1,2,3,4,5]
value = 3
pos1 = bisect(list_positive,value)
pos2 = bisect_left(list_positive,value)
pos3 = bisect_right(list_positive,value)
print(f"bisect:{pos1}")#bisect:4
print(f"bisect_left:{pos2}")#bisect_left:3
print(f"bisect_right:{pos3}")#bisect_right:4
这部分很简单,当list中存在我们需要查找的值时,bisect_left会让值插在左边,而,bisect和bisect_right会插在右边。为了更加清晰看懂这个区别,我们看下面:
from bisect import bisect,bisect_left,bisect_right
list_positive = [0,1,2,3,3,3,3,3,3,3,4,5]
value = 3
pos1 = bisect(list_positive,value)
pos2 = bisect_left(list_positive,value)
pos3 = bisect_right(list_positive,value)
print(f"bisect:{pos1}")#bisect:10
print(f"bisect_left:{pos2}")#bisect_left:3
print(f"bisect_right:{pos3}")#bisect_right:10
我拉长了3,现在对左右的概念更加清晰了吧?
1.2 值不存在于列表
看代码:
from bisect import bisect,bisect_left,bisect_right
list_positive = [0,1,2,4,5]
value = 3
pos1 = bisect(list_positive,value)
pos2 = bisect_left(list_positive,value)
pos3 = bisect_right(list_positive,value)
print(f"bisect:{pos1}")#bisect:3
print(f"bisect_left:{pos2}")#bisect_left:3
print(f"bisect_right:{pos3}")#bisect_right:3
显然,刚才3变得太长了现在萎了(笑)
我们看到三个值都是3,这里能看出很bisect设计中很重要的一点:
插入位置的索引是i(此处是3),相当于原索引大于和等于i的数向右推移!
可以返回看1.1,也是这个方式。
同理,bisect.insert()也是这个原理,但是这个方法用到较少,这里不讲了
记住这点在很多插插改改的数组问题中少思考很多
2.关于有序
网上关于bisect函数使用前提大都是莫能两可的有序
什么是有序?
看代码:
from bisect import bisect,bisect_left,bisect_right
list_positive = [5,4,3,2,1,0]
value = 3
pos1 = bisect(list_positive,value)
pos2 = bisect_left(list_positive,value)
pos3 = bisect_right(list_positive,value)
print(f"bisect:{pos1}")#bisect:6
print(f"bisect_left:{pos2}")#bisect_left:6
print(f"bisect_right:{pos3}")#bisect_right:6
5,4,3,2,1,0肯定算是有序对吧?
答案很离谱对吧?
没错,我写这篇帖子要讲的就一件事:
bisect函数使用前提是正序!而不是有序!
这是官方文档:
看完知道为啥上面代码的结果是666了吧?
3.最后
说实话这个问题,我Herllyc本人觉得算是个问题,因为我确实被坑了,我对一个逆序数组问题二分了半天,调试了半天,才发现问题出现在bisect,只能说怪我自己不求甚解,但是看到网上几乎没有人谈及这个问题,大多数都是复制粘贴的车轱辘话,甚至GPT3.5给我的答案也很逆天(GPT3.5也认为逆序可以使用bisect),也可以看出来这个问题比较冷门了。
本着CS领域的共享精神,我不希望关于这个问题还有更多“不求甚解”者磕磕绊绊,毕竟是一个非常简单的问题,但是属于知道了就是知道,不知道就会被坑的黑天鹅陷阱,总得来说也算是一个善意的提醒。
当然,这种文章更多还是面向一些和我一样的小可爱,真正的大佬或许根本不需要这样的善意提醒。(#^.^#)所以大佬们就当看一只小菜B的笑话吧