邀请大神——二分查找

Posted 数据有度

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了邀请大神——二分查找相关的知识,希望对你有一定的参考价值。

前言

bisect是Python内置实现的二分查找。在实际工作中的某些场景,比如学生成绩分级,可协助你写出优雅的代码。

需求

你需要将学生的成绩(0-100)转换成等级(ABCDEF)。

方案

新手方案

二话不说,if判断走起。

# codeing:utf-8

def grade(score):
    if score < 60:
        return 'F'
    elif score < 70:
        return 'E'
    elif score < 80:
        return 'D'
    elif score < 90:
        return 'C'
    elif score < 100:
        return 'B'
    else:
        return 'A'

if __name__ == '__main__':
    scores = [596065707880899095100]
    result = [grade(i) for i in scores]
    print(result)
    # ['F''E''E''D''D''C''C''B''B''A']

很好,我们出色地完成了任务。随后我们还需要按照学生的学时,商城会员的积分来进行分级。看来我们还需要茫茫多的if--elif--else判断。

Pythonic方案

仔细分析一下,类似的场景其实都包含了两个关键信息。一个是分界点,另外一个是等级。

比如学生成绩分级的分界点是[60, 70, 80, 90, 100],等级是'FEDCBA'

将成绩转换为分级的逻辑其实就是两步:

  • 在分界点(breakpoints)中找到学生成绩对应的位置(index)

  • 返回等级(grades)对应位置(index)的结果

# codeing:utf-8

from bisect import bisect

def grade(score, breakpoints=[60708090100], grades='FEDCBA'):
    i = bisect(breakpoints, score)
    return grades[i]

if __name__ == '__main__':
    scores = [596065707880899095100]
    result = [grade(i) for i in scores]
    print(result)
    # ['F''E''E''D''D''C''C''B''B''A']

同样地,根据商城会员的积分来进行分级。

breakpoints = [100020003000]
grades = ['普通会员''中级会员''高级会员''VIP']
scores = [4991023202030004999]
print([grade(i, breakpoints=breakpoints, grades=grades) for i in scores])

# ['普通会员''中级会员''高级会员''VIP''VIP']

总结

防踩坑Tips:

  • grades的元素应该比breakpoints多一个(可以想想原因)。

  • bisect模块提供了bisect_leftbisect_right两个方法,区别在于当元素相等时,返回的index是在breakpoint的左边还是右边。

  • 例子中用的bisect.bisect就是bisect_right

  • 更详细的说明,请参看Python官方文档bisect — Array bisection algorithm

孤立地来看bisect,可能会觉得仅仅是二分查找而已。然而在工作中,根据场景使用bisect,往往会给你带来惊喜。这里其实还是一个应用算法的能力。

有空也可以多翻翻Python文档,很多内置库都提供了方便的功能。比如上面学生成绩分级的例子就是官方文档提供的。

练习

请使用bisect_left改写例子中的代码。


以上是关于邀请大神——二分查找的主要内容,如果未能解决你的问题,请参考以下文章

景驰无人驾驶 1024 编程邀请赛 B题 计算几何+裸二分匹配

听justjavac大神live前端的入门与进阶小笔记

二分查找常见套路与分析

二分查找常见套路与分析

java 二分查找法

代码题(12)— 二分查找