如何用Python实现二分查找寻找满足is_smaller的最大20位数字
当然可以用二分查找解决,这是最优方案!
你的需求本质上就是在**有序区间[0, 99999999999999999999]**中寻找最大的满足is_smaller(x) == True的数值——这完全是二分查找的典型应用场景,而且效率极高。
为什么二分查找可行?
因为is_smaller函数的返回值具有明确的单调性:
- 所有≤目标数的x,返回
True - 所有>目标数的x,返回
False
这种单调特性正好匹配二分查找的核心前提,我们可以通过每次将搜索范围缩小一半,快速定位到目标值。
具体实现思路(以Python为例)
def find_max_target(): left = 0 right = 99999999999999999999 # 即10^20 - 1 while left < right: # 用向上取整的方式计算mid,避免相邻边界时的死循环 mid = left + (right - left + 1) // 2 if is_smaller(mid): # mid满足条件,说明目标数≥mid,把左边界移到mid left = mid else: # mid不满足条件,目标数<mid,把右边界移到mid-1 right = mid - 1 # 循环结束时left == right,就是我们要找的最大值 return left
关键细节说明
- 为什么用向上取整的mid?
如果用普通的(left + right) // 2,当left和right相邻时(比如left=5,right=6,目标数是6),计算出的mid=5,调用is_smaller(5)返回True后,left会更新为5,循环会陷入死循环。而向上取整的mid会直接取到6,判断后更新left为6,循环顺利结束。 - 时间复杂度:最多需要约
log2(10^20) ≈ 67次is_smaller调用,这比任何线性搜索方法高效得多(线性搜索最坏要10^20次,完全不现实)。 - 大数兼容:Python原生支持超大整数,所以不用担心计算mid时的溢出问题。如果是在其他强类型语言中,记得用
left + (right - left +1)//2代替(left+right+1)//2,避免整数溢出。
验证小例子
假设目标数是6,范围简化为[0,9]:
- 初始left=0,right=9 → mid=(0+9+1)//2=5 →
is_smaller(5)=True→ left=5 - left=5,right=9 → mid=(5+9+1)//2=7 →
is_smaller(7)=False→ right=6 - left=5,right=6 → mid=(5+6+1)//2=6 →
is_smaller(6)=True→ left=6 - left=right=6,循环结束,返回6,结果正确。
内容的提问来源于stack exchange,提问作者boolean.is.null
相关产品推荐
相关产品推荐

