网站首页 > java教程 正文
上篇我们讲解了八种排序算法的原理,本文再深度剖析如何运用二分查找算法。
一、二分查找的实现
对于给定的已经有序的数列,我们需要在该数列中查找是否存在某个元素。
每次都与数列最中间的元素进行比较,可以缩小一半的查找区间,直至找到目标元素或者区间被缩小为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;
}
四、总结
在实际的查找业务场景中,凡是可以使用二分查找的问题都可以使用散列表和二叉查找树来完成,而且后面两者的使用频率要更高。
什么情况下才使用二分查找呢?用于求解近似查找的问题上,比如上面描述的四种二分查找变体问题,而这类问题使用散列表、二叉查找树或者别的数据结构和算法就不太好实现。
猜你喜欢
- 2025-09-13 面试中如果这样写二分查找_面试分怎么查
- 2025-09-13 图解算法:二分查找树_二分查找法判定树
- 2025-09-13 java中Arrays类中,binarySearch()方法的返回值问题
- 2025-09-13 单片机上实现二分查找+线性插值计算
- 2025-09-13 数据结构之二分查找:c++版本_二分查找算法c语言递归
- 2025-09-13 玩蛇(Python) - 算法:二分查找(Binary Search)
- 2025-09-13 高级Java面试之二分法查找_java二分查找算法代码
- 2025-09-13 【程序员常用十算法】二分查找法—5分钟掌握
- 2025-09-13 看动图学算法(二):二分查找算法的原理和Java讲解
- 2025-09-13 发现了二分查找的秘密_二分查找细节
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)