/**
* 二分查找。循环和递归两种方法实现。
* <p>创建日期:2020-05-22 12:20</p>
*
* @author PengHao
*/
public class BinarySearch {
/**
* 循环实现的二分查找算法。时间复杂度为O(log(n)),空间复杂度为O(1)。
*
* @param src 待查找的数组
* @param key 待查找的关键字
* @return 如果数组中存在key,则返回key在src中的索引,如果找不到,返回-1。
*/
public static int indexOfLoop(int[] src, int key) {
if (src == null) {
System.err.println("待查找数组不能为null");
return -1;
} else if (src.length == 0) {
return -1;
}
int left = 0, mid = 0, right = src.length - 1;
while (left < right) {
mid = left + (right - left >> 1);
if (src[mid] >= key) {
right = mid;
} else {
left = mid + 1;
}
}
return src[left] == key ? left : -1;
}
/**
* 递归实现的二分查找算法。时间复杂度为O(log(n)),空间复杂度为O(1)。如果待查找数组为null或者长度为0,则返回-1,
* 否则调用{@link #indexOfRecursion(int[], int, int, int)}方法
*
* @param src 待查找的数组
* @param key 待查找的关键字
* @return 如果在src中能找到key,则返回key在src中的索引,否则返回-1。
* @see #indexOfRecursion(int[], int, int, int)
*/
public static int indexOfRecursion(int[] src, int key) {
if (src == null) {
System.err.println("待查找数组不能为null");
return -1;
} else if (src.length == 0) {
return -1;
}
return indexOfRecursion(src, 0, src.length - 1, key);
}
/**
* 尾递归实现的二分查找算法。时间复杂度为O(log(n)),空间复杂度为O(1)。如果区间[from, to]不存在,则返回-1。
* 如果在数组的区间[from, to]中找到key,则返回索引。如果找不到,则递归调用自己并缩小区间。
*
* @param src 待查找的数组
* @param key 待查找的关键字
* @return 如果在src中能找到key,则返回key在src中的索引,否则返回-1。
* @see #indexOfRecursion(int[], int)
*/
private static int indexOfRecursion(int[] src, int from, int to, int key) {
if (from > to) {
return -1;
}
int mid = from + (to - from >> 1);
if (src[mid] < key) {
return indexOfRecursion(src, mid + 1, to, key);
} else if (src[mid] > key) {
return indexOfRecursion(src, from, mid - 1, key);
} else {
return mid;
}
}
}