/**
* 二分查找。循環和遞歸兩種方法實作。
* <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;
}
}
}