二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法,前提是数据结构必须先排好序,可以在数据规模的对数时间复杂度内完成查找。但是,二分查找要求线性表具有有随机访问的特点(例如数组),也要求线性表能够根据中间元素的特点推测它两侧元素的性质,以达到缩减问题规模的效果。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
//不使用递归实现(while循环)
/**
* 二分查找,找到该值在数组中的下标,否则返回-1
*/
static int binarySerach(int[] array, int key) {
int left = 0;
int right = array.length - 1;
if(key < arr[low] || key > arr[high] || low > high){
return -1;
}
// 这里必须是 <=
while (left <= right) {
int mid = (left + right) / 2;
if (array[mid] == key) {
return mid;
}
else if (array[mid] < key) {
left = mid + 1;
}
else {
right = mid - 1;
}
}
return -1;
}
//递归实现
public static int recursionBinarySearch(int[] arr,int key,int low,int high){
if(key < arr[low] || key > arr[high] || low > high){
return -1;
}
int middle = (low + high) / 2; //初始中间位置
if(arr[middle] > key){
//比关键字大则关键字在左区域
return recursionBinarySearch(arr, key, low, middle - 1);
}else if(arr[middle] < key){
//比关键字小则关键字在右区域
return recursionBinarySearch(arr, key, middle + 1, high);
}else {
return middle;
}
}
二分查找总结
// 这里必须是 <=
while (left <= right) {
int mid = (left + right) / 2;
if (array[mid] ? key) {//2.判断出比较符号
//... right = mid - 1;
}
else {
// ... left = mid + 1;
}
}
return xxx;//1.首先判断返回left,还是right
时间复杂度
采用的是分治策略
最坏的情况下两种方式时间复杂度一样:O(log2N)
最好情况下为:O(1)
空间复杂度
算法的空间复杂度并不是计算实际占用的空间,而是计算整个算法的辅助空间单元的个数
非递归方式:
由于辅助空间是常数级别的,所以:
空间复杂度是O(1);
递归方式:
递归的次数和深度都是log2 N,每次所需要的辅助空间都是常数级别的,所以:
空间复杂度:O(log2N )