每周一算法之二分查找(Kotlin描述)

本文介绍了二分查找算法的时间复杂度、基本思想、步骤,并通过Kotlin语言详细阐述了实现过程,包括避免Java中可能出现的溢出问题。同时,文章探讨了位运算在Kotlin和Java中的应用,并提供了LeetCode上的相关练习题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简述: 从这篇文章起就会开启另一个系列就是上篇文章中提到的每周学习一个基本算法,会结合LeetCode上题目来做分析。解题的语言一般是Kotlin或Java. 如果涉及到一些有关Kotlin的知识点也会做一些介绍。如果平时就养成学习数据结构算法以及刷题的习惯,不管今后你是面试(愿从此再也不是面试造火箭平时拧螺丝了)或在实际上工作中都会对你有很大帮助。这也是这个系列文章的目的。

一、时间复杂度

最坏时间复杂度 O(log n)

最优时间复杂度 O(1)

平均时间复杂度 O(log n)

二、基本思想

在一个有序的列表中,要查找的数与列表中间的位置相比,若相等说明找到了,若要查找的数大于列表中间的数,说明要查找的数可能在有序列表的后半部分;若要查找的数小于列表中间的数,说明要查找的数可能在有序列表的前半部分;然后类似上述操作缩短查找范围,最后直到查找到最后一个数,如果不等于要查找的数,那么查找范围就为空。

三、算法步骤

给定一个包含n个带值的元素数组或序列A[0], … A[n-1],使A[0] <= … <= A[n-1],以及目标值Target.

  • 1、令 low = 0, high = n - 1
  • 2、若low > high, 则表示查找失败结束
  • 3、令mid(中间值元素)为 (low + high) / 2的值向下取整 (注意: 在具体实现中为了防止溢出,一般会采用 low + (high - low) / 2的值向下取整 或者直接采用位运算的移位运算来实现除2的操作。这个后面会有具体题目来说明)
  • 4、若Target > A[mid], 令 low = mid + 1 (说明要查找的值在序列或数组后半部分(除去自身),移动low游标,缩小查找范围),并回到步骤2
  • 5、如果Target < A[mid], 令 high = mid - 1 (说明要查找的值在序列或数组前半部分(除去自身),移动high游标,缩小查找范围),并回到步骤2
  • 6、如果Target == A[mid], 查找成功并结束,返回mid下标值。

四、算法过程演示

五、代码实现(Kotlin语言描述)

二分查找算法主要有两种实现方式,一种是循环递推的方式,另一种则是递归的方式

  • 1、 循环递推实现方式
  • 2、递归实现方式

六、为什么Java中mid = (low + high) / 2方式会溢出

相信刷过LeetCode题目的小伙伴们可能会在刷二分查找的题目过程会遇到超过时间限制的错误

不知道大家有没有去分析过为什么会得到超时啊,我都用了二分查找了时间复杂度都变成 O(log n) 呢,为啥还会超时呢。实际上是int数据类型溢出导致出现负数,使得代码进入了死循环,然后导致超时,最后OJ给你个超出时间错误。

  • 1、出现问题的原因

我们可以确定 lowhigh 都是非负数,那么也就是二进制表示的最高位符号位是0,并且lowhigh 都是31位二进制的整数

假设下面这种场景:

high = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824 (Integer.MAX_VALUE的一半)
low  = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824 (Integer.M
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

熊喵先生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值