三分查找(Ternary Search),查找一次就可以排除整个有序线性表的2/3,查找效率更高。最差时间复杂度O(log3 n),最优时间复杂度
O(1),空间复杂度O(1)。
Java代码示例:
/**
* 使用递归的方法
* 三分数组搜索
* @param arr 数组
* @param key 目标数值
* @param s 数组下标开始位置
* @param e 数组下标结束位置
* @return 目标下标位
*/
public int ternaryFind(int[] arr, int key, int s, int e){
if (s < e){
return -1;
}
// 第一个范围点数组长度的1/3
int midPos1 = s + (e - s)/3;
// 第二个范围点数组长度的2/3
int midPos2 = s + 2*(e - s)/3;
if (key == arr[midPos1]){
return midPos1;
}else if (key == arr[midPos2]){
return midPos2;
}else if (key < arr[midPos1]){
return ternaryFind(arr, key, s, midPos1-1);
}else if (key > arr[midPos2]){
return ternaryFind(arr, key, midPos2 + 1, e);
}else {
return ternaryFind(arr, key, midPos1 + 1, midPos2 - 1);
}
}
public<T extends Comparable<T>> int ternaryFind(T[] arr, T key, int s, int e){
if (s > e){
return -1;
}
int midPos1 = s + (e - s)/3;
int midPos2 = s + 2*(e - s)/3;
int cmpResult1 = key.compareTo(arr[midPos1]);
int cmpResult2 = key.compareTo(arr[midPos2]);
if (cmpResult1 == 0){
return midPos1;
}else if (cmpResult2 == 0){
return midPos2;
}else if (cmpResult1 < 0){
return ternaryFind(arr, key, s, midPos1 - 1);
}else if (cmpResult2 > 0){
return ternaryFind(arr, key, midPos2 + 1, e);
}else {
return ternaryFind(arr, key, midPos1 + 1, midPos2 - 1);
}
}
/**
* 三分搜索法
* 迭代循环
* @param arr 数组
* @param key 目标对象
* @param s 数组下标开始位
* @param e 数组下标结束位
* @param <T> 泛型
* @return 目标下标位置
*/
public<T extends Comparable<T>> int ternaryFindCycle(T[] arr, T key, int s, int e){
/**
* 1、一次循环排除2/3
* 推荐
*/
while (s >=0 && e >= s){
int midPos1 = s + (e - s)/3;
int midPos2 = s + 2*(e - s)/3;
int cmpResult1 = key.compareTo(arr[midPos1]);
int cmpResult2 = key.compareTo(arr[midPos2]);
if (cmpResult1 == 0){
return midPos1;
}else if (cmpResult2 == 0){
return midPos2;
}else if (cmpResult1 < 0){
e = midPos1 - 1;
}else if (cmpResult2 > 0){
s = midPos2 + 1;
}else {
s = midPos1 + 1;
e = midPos2 - 1;
}
}
/**
* 2、一次循环排除1/3或者2/3
* 不推荐
*/
while (s >=0 && e >= s){
int midPos1 = s + (e - s)/3;
int cmpResult1 = key.compareTo(arr[midPos1]);
if (cmpResult1 == 0){
return midPos1;
}else if (cmpResult1 < 0){
e = midPos1 - 1;
}else {
s = midPos1 + 1;
}
}
return -1;
}