秒懂如何运用二分查找算法
上篇我们讲解了八种排序算法的原理,本文再深度剖析如何运用二分查找算法。一、二分查找的实现
对于给定的已经有序的数列,我们需要在该数列中查找是否存在某个元素。
每次都与数列最中间的元素进行比较,可以缩小一半的查找区间,直至找到目标元素或者区间被缩小为0,元素不存在。比如下面的数列中,我们想要查找元素19,那么大致的过程就是这样的:
二分查找过程示意图
使用代码实现如下: public static void main(String[] args) { int[] data = {8, 11, 19, 23, 27, 33, 45, 55, 67, 98}; int result = binarySearch(data, data.length, 19); log.info("查找元素19的位置是:{}", result); } public static int binarySearch(int[] data, int size, int target) { int low = 0; int high = size - 1; while (low <= high) { int middle = (low + high) / 2; if (data[middle] == target) { return middle; } else if (data[middle] < target) { low = middle + 1; } else { high = middle - 1; } } log.info("元素{}查找不存在!", target); return -1; }
二分查找的时间复杂度是O(logn),对数阶时间复杂度的算法效率非常高。 二、二分查找的特点及使用场景
二分查找必须依赖以下条件才能发挥作用: 数据结构一定要是顺序表,比如数组。如果是不支持随机访问的数据结构,那么二分查找就无法使用; 待查找的数列一定要是有序的。如果给定的数列是无序的,那么我们就必须先使用排序算法将数列进行排序,否则也无法使用二分查找; 不适合频繁插入和删除的数列;因为数列需要保持有序,要么在插入和删除的时候保证有序,要么在插入数列后使用排序算法进行排序,这些都是时间开销; 不适合数据量太小的数列;数列太小,直接顺序遍历说不定更快,也更简单;但是有一种场景除外,就是每次元素与元素的比较是比较耗时的,这个比较操作耗时占整个遍历算法时间的大部分,那么使用二分查找就能有效减少元素比较的次数,从而节约时间; 不适合数据量太大的数列;二分查找作用的数据结构是顺序表,也就是数组,数组是需要连续的内存空间的,系统并不一定有这么大的连续内存空间可以使用; 三、二分查找相关的变体
查找第一个等于给定值的元素 public static void main(String[] args) { int[] data = {8, 11, 19, 19, 19, 33, 45, 55, 67, 98}; int result = binarySearch1(data, data.length, 19); log.info("查找元素19的位置是:{}", result); } public static int binarySearch1(int[] data, int size, int target) { int low = 0; int high = size - 1; while(low <= high){ int middle = (low + high) / 2; if(data[middle] > target){ high = middle - 1; } else if(data[middle] < target){ low = middle + 1; } else { // 当前元素等于目标元素,但是不一定是第一个等于目标元素的 if((middle == 0) || (data[middle-1] != target)){ // 说明当前middle是第一个等于目标元素的 return middle; } else { // 继续在middle的前半区间进行查找 high = middle - 1; } } } return -1; }
查找最后一个等于给定值的元素 else { // 当前元素等于目标元素,但是不一定是最后一个等于目标元素的 if((middle == size-1) || (data[middle+1] != target)){ // 说明当前middle是最后一个等于目标元素的 return middle; } else { // 继续在middle的后半区间进行查找 low = middle + 1; } }
查找第一个大于等于给定值的元素 public static int binarySearch3(int[] data, int size, int target) { int low = 0; int high = size - 1; while(low <= high){ int middle = (low + high) / 2; if(data[middle] >= target){ if(middle == 0 || data[middle-1] < target){ // 是第一个大于等于target的位置 return middle; } else { // 继续往middle的前半部分去找 high = middle - 1; } } else { // 继续往middle的后半部分去找 low = middle + 1; } } return -1; }
查找最后一个小于等于给定值的元素 public static int binarySearch4(int[] data, int size, int target) { int low = 0; int high = size - 1; while(low <= high){ int middle = (low + high) / 2; if(data[middle] <= target){ if(middle == (size-1) || data[middle+1] > target){ return middle; } else { low = middle + 1; } } else { high = middle - 1; } } return -1; }四、总结
在实际的查找业务场景中,凡是可以使用二分查找的问题都可以使用散列表和二叉查找树来完成,而且后面两者的使用频率要更高。
什么情况下才使用二分查找呢?用于求解近似查找的问题上,比如上面描述的四种二分查找变体问题,而这类问题使用散列表、二叉查找树或者别的数据结构和算法就不太好实现。
100款新国标奶粉维生素D大盘点,它对宝宝竟如此重要!最近正值春季补钙补维生素D的关键时期,而总有妈妈在为宝宝选择补剂时忽略了其实奶粉中就含有丰富的维生素D。目前新国标已经正式实施,有28家乳企,100个品牌,旗下294款产品通过新国
宝宝缺钙又到了一年一度的春长了,好多家长都想利用这个春季给孩子多补充营养,好长身体,朋友的孩子却总不长个子,前些日子去检查身体说是缺钙,咨询医生说主要有以下几个病因1。户外运动,晒太阳太少
宝宝春季吃什么丝瓜蒸牛肉食材牛肉丝瓜葱姜做法1。牛肉清洗干净切薄片,越薄越嫩,加入葱姜淀粉酱油蚝油抓匀,再加入少许辅食油抓匀腌制10分钟备用。2。丝瓜去皮切滚刀块,再加入少许盐拌匀,放入碗中,腌
无畏契约控场者守卫前锋决斗者,全角色ampampamp技能介绍无畏契约相信玩游戏的都很熟悉了,以前都是翻墙去玩,21年9月腾讯引进了这款游戏,但一直等到现在还没上。据悉是今年2023年会上线,但还不确定时间,不过我们可以先来了解一下这款游戏的
虞姬完美出装怎么现在还有人玩虞姬在出破晓啊。绝大数人都在误导你对虞姬的理解,玩虞姬所遇到的问题就是发育慢伤害低,尤其是出破晓的时候,不仅装备成型特别慢,而且它的攻速加成在后期对虞姬没有任何提升
王者荣耀雅典娜和关羽相对比,你更喜欢哪个?关羽被动技能一骑当千关羽每主动移动一段距离,速度将得到提升,移动达到更远距离时进入冲锋姿态,冲锋时造成普攻伤害并额外附带自身最大生命值的百分比物理伤害。技能1单刀赴会关羽旋转大刀对
三国群英传2不分敌我的武将技伏焰游戏新春创作纪三国群英传2中有各种各样的武将技,其中大部分武将技是分敌我的,只对自己有利,对敌方不利,但是也有很少的几个武将技是不分敌我的,其中伏焰这个武将技最常见。伏焰,在平坦的
王者荣耀中伽罗和蔡文姬哪个厉害呢?伽罗和蔡文姬是一对非常不错的下路组合,如果将两者分开的话,伽罗要强于蔡文姬,因为蔡文姬本身伤害不足。蔡文姬最大的特点是帮助队友回血,它的技能缺乏伤害,即便是出全法装的蔡文姬,也很难
吃饭九忌一忌吃得过饱。进食过量,超过了胃肠道的消化能力,时间长了,会使胃功能下降。二忌吃得太快。吃饭太快,唾液不能充分和食物混合,不利于消化。三忌分神。吃饭时不要看书报电视电脑玩手机或高声
原来提肛运动的好处这么多,一起来科普一下吧养生是人们经常挂在嘴边的一句话,不管是在生活中,还是在工作中,很多人都喜欢用一些养生的小妙招来保养身体,比如泡脚艾灸喝枸杞水等等。今天要给大家介绍的是提肛运动,可能有些人对这个比较
低钠盐加碘盐无碘盐吃哪种盐更有利健康?一文了解根据2022年世界减盐周的报告显示,2017年全球因高盐饮食死亡的人数达300万人,在我国死亡人数达165万人。尤其是那些平时吃盐多口味重血压高的人群,其实只要换一种盐,就能够很大