二分查找
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。 但是,折半查找要求数组必须采用顺序存储结构,而且数组中元素按关键字有序排列。
二分查找算法思想
有序的序列,每次都是以序列的中间位置的数来与待查找的关键字进行比较,每次缩小一半的查找范围,直到匹配成功。
一个情景:将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
二分查找优缺点
优点:是比较次数少,查找速度快,平均性能好;
缺点:是要求待查表为有序表,且插入删除困难。
因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
使用条件:查找序列是顺序结构,有序。
例子
查找第一个值等于给定值的元素下标
package com.cyj.demo;
/**
*
* Function:
* Author:@author chenyongjia
* Date:2019-11-04 23:15
* Desc:二分查找变形题目
*/
public class BinarySearch {
public static void main(String[] args) {
int[] a = {1, 3, 4, 5, 6, 8, 8, 8, 11, 18};
System.out.println(bsearch4(a, a.length, 12));
}
/**
* 变形一:二分查找变形题,查找第一个值等于给定值的元素下标
* int[] a = {1, 3, 4, 5, 6, 8, 8, 8, 11, 18};
* 如查找8,应该返回5
*
* @param array
* @param n
* @param value
* @return
*/
private static int bsearch1(int[] array, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (array[mid] > value) {
high = mid - 1;
} else if (array[mid] < value) {
low = mid + 1;
} else {
if (mid == 0 || array[mid - 1] != value) {
return mid;
} else {
high = mid - 1;
}
}
}
return -1;
}
这里查找第一个值等于给定值的元素下标,二分经常是用来查找给定值的下标,但是当有很多相同值的时候,这个算法就是查询第一个值的。
查找最后一个值等于给定值的元素
/**
* 变形:查找最后一个值等于给定值的元素
*
* @param array
* @param n
* @param value
* @return
*/
private static int bsearch2(int[] array, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (array[mid] > value) {
high = mid - 1;
} else if (array[mid] < value) {
low = mid + 1;
} else {
if (mid == n - 1 || array[mid + 1] != value) {
return mid;
} else {
low = mid + 1;
}
}
}
return -1;
}
这里查找最后一个值等于给定值的元素,跟上边一个类似,这里是查询最后一个。
查找第一个大于等于给定值的元素
/**
* 变形:查找第一个大于等于给定值的元素
*
* @param array
* @param n
* @param value
* @return
*/
private static int bsearch3(int[] array, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (array[mid] >= value) {
if ((mid == 0) || (array[mid - 1] < value)) {
return mid;
} else {
high = mid - 1;
}
} else {
low = mid + 1;
}
}
return -1;
}
查找最后一个小于等于给定值的元素
/**
* 变形:查找最后一个小于等于给定值的元素
* int[] a = {1, 3, 4, 5, 6, 8, 8, 8, 11, 18};
* 如value = 12,则应该返回11的下标8
* System.out.println(bsearch4(a, a.length, 12));
*
* @param array
* @param n
* @param value
* @return
*/
private static int bsearch4(int[] array, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (array[mid] > value) {
high = mid - 1;
} else {
if (mid == n - 1 || array[mid + 1] > value) {
return mid;
} else {
low = mid + 1;
}
}
}
return -1;
}
}
空间复杂度
算法的空间复杂度并不是计算实际占用的空间,而是计算整个算法的辅助空间单元的个数
非递归方式:
- 由于辅助空间是常数级别的所以:
- 空间复杂度是O(1);
递归方式:
- 递归的次数和深度都是log2 N,每次所需要的辅助空间都是常数级别的:
- 空间复杂度:O(log2N )
最后
-
更多参考精彩博文请看这里:《陈永佳的博客》
-
喜欢博主的小伙伴可以加个关注、点个赞哦,持续更新嘿嘿!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/97632.html